Merge tag 'amd-drm-next-5.13-2021-04-12' of https://gitlab.freedesktop.org/agd5f/linux into drm-next
amd-drm-next-5.13-2021-04-12: amdgpu: - Re-enable GPU reset on VanGogh - Enable DPM flags for SMART_SUSPEND and MAY_SKIP_RESUME - Disentangle HG from vga_switcheroo - S0ix fixes - W=1 fixes - Resource iterator fixes - DMCUB updates - UBSAN fixes - More PM API cleanup - Aldebaran updates - Modifier fixes - Enable VCN load balancing with asymmetric engines - Rework BO structs - Aldebaran reset support - Initial LTTPR display work - Display MALL fixes - Fall back to YCbCr420 when YCbCr444 fails - SR-IOV fixes - RAS updates - Misc cleanups and fixes radeon: - Typo fixes - Fix error handling for firmware on r6xx - Fix a missing check in DP MST handling Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20210412220732.3845-1-alexander.deucher@amd.com
This commit is contained in:
commit
cd951b3971
@ -71,7 +71,7 @@ amdgpu-y += \
|
||||
vi.o mxgpu_vi.o nbio_v6_1.o soc15.o emu_soc.o mxgpu_ai.o nbio_v7_0.o vega10_reg_init.o \
|
||||
vega20_reg_init.o nbio_v7_4.o nbio_v2_3.o nv.o navi10_reg_init.o navi14_reg_init.o \
|
||||
arct_reg_init.o navi12_reg_init.o mxgpu_nv.o sienna_cichlid_reg_init.o vangogh_reg_init.o \
|
||||
nbio_v7_2.o dimgrey_cavefish_reg_init.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o
|
||||
nbio_v7_2.o dimgrey_cavefish_reg_init.o hdp_v4_0.o hdp_v5_0.o aldebaran_reg_init.o aldebaran.o
|
||||
|
||||
# add DF block
|
||||
amdgpu-y += \
|
||||
@ -88,7 +88,7 @@ amdgpu-y += \
|
||||
|
||||
# add UMC block
|
||||
amdgpu-y += \
|
||||
umc_v6_1.o umc_v6_0.o umc_v8_7.o
|
||||
umc_v6_0.o umc_v6_1.o umc_v6_7.o umc_v8_7.o
|
||||
|
||||
# add IH block
|
||||
amdgpu-y += \
|
||||
@ -179,9 +179,14 @@ amdgpu-y += \
|
||||
smuio_v11_0_6.o \
|
||||
smuio_v13_0.o
|
||||
|
||||
# add reset block
|
||||
amdgpu-y += \
|
||||
amdgpu_reset.o
|
||||
|
||||
# add amdkfd interfaces
|
||||
amdgpu-y += amdgpu_amdkfd.o
|
||||
|
||||
|
||||
ifneq ($(CONFIG_HSA_AMD),)
|
||||
AMDKFD_PATH := ../amdkfd
|
||||
include $(FULL_AMD_PATH)/amdkfd/Makefile
|
||||
|
407
drivers/gpu/drm/amd/amdgpu/aldebaran.c
Normal file
407
drivers/gpu/drm/amd/amdgpu/aldebaran.c
Normal file
@ -0,0 +1,407 @@
|
||||
/*
|
||||
* Copyright 2021 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "aldebaran.h"
|
||||
#include "amdgpu_reset.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_dpm.h"
|
||||
#include "amdgpu_job.h"
|
||||
#include "amdgpu_ring.h"
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_psp.h"
|
||||
#include "amdgpu_xgmi.h"
|
||||
|
||||
static struct amdgpu_reset_handler *
|
||||
aldebaran_get_reset_handler(struct amdgpu_reset_control *reset_ctl,
|
||||
struct amdgpu_reset_context *reset_context)
|
||||
{
|
||||
struct amdgpu_reset_handler *handler;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle;
|
||||
|
||||
if (reset_context->method != AMD_RESET_METHOD_NONE) {
|
||||
dev_dbg(adev->dev, "Getting reset handler for method %d\n",
|
||||
reset_context->method);
|
||||
list_for_each_entry(handler, &reset_ctl->reset_handlers,
|
||||
handler_list) {
|
||||
if (handler->reset_method == reset_context->method)
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
|
||||
if (adev->gmc.xgmi.connected_to_cpu) {
|
||||
list_for_each_entry(handler, &reset_ctl->reset_handlers,
|
||||
handler_list) {
|
||||
if (handler->reset_method == AMD_RESET_METHOD_MODE2) {
|
||||
reset_context->method = AMD_RESET_METHOD_MODE2;
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(adev->dev, "Reset handler not found!\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int aldebaran_mode2_suspend_ip(struct amdgpu_device *adev)
|
||||
{
|
||||
int r, i;
|
||||
|
||||
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
|
||||
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
|
||||
|
||||
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
|
||||
if (!(adev->ip_blocks[i].version->type ==
|
||||
AMD_IP_BLOCK_TYPE_GFX ||
|
||||
adev->ip_blocks[i].version->type ==
|
||||
AMD_IP_BLOCK_TYPE_SDMA))
|
||||
continue;
|
||||
|
||||
r = adev->ip_blocks[i].version->funcs->suspend(adev);
|
||||
|
||||
if (r) {
|
||||
dev_err(adev->dev,
|
||||
"suspend of IP block <%s> failed %d\n",
|
||||
adev->ip_blocks[i].version->funcs->name, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
adev->ip_blocks[i].status.hw = false;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
aldebaran_mode2_prepare_hwcontext(struct amdgpu_reset_control *reset_ctl,
|
||||
struct amdgpu_reset_context *reset_context)
|
||||
{
|
||||
int r = 0;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle;
|
||||
|
||||
dev_dbg(adev->dev, "Aldebaran prepare hw context\n");
|
||||
/* Don't suspend on bare metal if we are not going to HW reset the ASIC */
|
||||
if (!amdgpu_sriov_vf(adev))
|
||||
r = aldebaran_mode2_suspend_ip(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void aldebaran_async_reset(struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_reset_handler *handler;
|
||||
struct amdgpu_reset_control *reset_ctl =
|
||||
container_of(work, struct amdgpu_reset_control, reset_work);
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle;
|
||||
|
||||
list_for_each_entry(handler, &reset_ctl->reset_handlers,
|
||||
handler_list) {
|
||||
if (handler->reset_method == reset_ctl->active_reset) {
|
||||
dev_dbg(adev->dev, "Resetting device\n");
|
||||
handler->do_reset(adev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int aldebaran_mode2_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
/* disable BM */
|
||||
pci_clear_master(adev->pdev);
|
||||
adev->asic_reset_res = amdgpu_dpm_mode2_reset(adev);
|
||||
return adev->asic_reset_res;
|
||||
}
|
||||
|
||||
static int
|
||||
aldebaran_mode2_perform_reset(struct amdgpu_reset_control *reset_ctl,
|
||||
struct amdgpu_reset_context *reset_context)
|
||||
{
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)reset_ctl->handle;
|
||||
int r = 0;
|
||||
|
||||
dev_dbg(adev->dev, "aldebaran perform hw reset\n");
|
||||
if (reset_context->hive == NULL) {
|
||||
/* Wrong context, return error */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
list_for_each_entry(tmp_adev, &reset_context->hive->device_list,
|
||||
gmc.xgmi.head) {
|
||||
mutex_lock(&tmp_adev->reset_cntl->reset_lock);
|
||||
tmp_adev->reset_cntl->active_reset = AMD_RESET_METHOD_MODE2;
|
||||
}
|
||||
/*
|
||||
* Mode2 reset doesn't need any sync between nodes in XGMI hive, instead launch
|
||||
* them together so that they can be completed asynchronously on multiple nodes
|
||||
*/
|
||||
list_for_each_entry(tmp_adev, &reset_context->hive->device_list,
|
||||
gmc.xgmi.head) {
|
||||
/* For XGMI run all resets in parallel to speed up the process */
|
||||
if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
if (!queue_work(system_unbound_wq,
|
||||
&tmp_adev->reset_cntl->reset_work))
|
||||
r = -EALREADY;
|
||||
} else
|
||||
r = aldebaran_mode2_reset(tmp_adev);
|
||||
if (r) {
|
||||
dev_err(tmp_adev->dev,
|
||||
"ASIC reset failed with error, %d for drm dev, %s",
|
||||
r, adev_to_drm(tmp_adev)->unique);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* For XGMI wait for all resets to complete before proceed */
|
||||
if (!r) {
|
||||
list_for_each_entry(tmp_adev,
|
||||
&reset_context->hive->device_list,
|
||||
gmc.xgmi.head) {
|
||||
if (tmp_adev->gmc.xgmi.num_physical_nodes > 1) {
|
||||
flush_work(&tmp_adev->reset_cntl->reset_work);
|
||||
r = tmp_adev->asic_reset_res;
|
||||
if (r)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(tmp_adev, &reset_context->hive->device_list,
|
||||
gmc.xgmi.head) {
|
||||
mutex_unlock(&tmp_adev->reset_cntl->reset_lock);
|
||||
tmp_adev->reset_cntl->active_reset = AMD_RESET_METHOD_NONE;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int aldebaran_mode2_restore_ip(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_firmware_info *ucode_list[AMDGPU_UCODE_ID_MAXIMUM];
|
||||
struct amdgpu_firmware_info *ucode;
|
||||
struct amdgpu_ip_block *cmn_block;
|
||||
int ucode_count = 0;
|
||||
int i, r;
|
||||
|
||||
dev_dbg(adev->dev, "Reloading ucodes after reset\n");
|
||||
for (i = 0; i < adev->firmware.max_ucodes; i++) {
|
||||
ucode = &adev->firmware.ucode[i];
|
||||
if (!ucode->fw)
|
||||
continue;
|
||||
switch (ucode->ucode_id) {
|
||||
case AMDGPU_UCODE_ID_SDMA0:
|
||||
case AMDGPU_UCODE_ID_SDMA1:
|
||||
case AMDGPU_UCODE_ID_SDMA2:
|
||||
case AMDGPU_UCODE_ID_SDMA3:
|
||||
case AMDGPU_UCODE_ID_SDMA4:
|
||||
case AMDGPU_UCODE_ID_SDMA5:
|
||||
case AMDGPU_UCODE_ID_SDMA6:
|
||||
case AMDGPU_UCODE_ID_SDMA7:
|
||||
case AMDGPU_UCODE_ID_CP_MEC1:
|
||||
case AMDGPU_UCODE_ID_CP_MEC1_JT:
|
||||
case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL:
|
||||
case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM:
|
||||
case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM:
|
||||
case AMDGPU_UCODE_ID_RLC_G:
|
||||
ucode_list[ucode_count++] = ucode;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
/* Reinit NBIF block */
|
||||
cmn_block =
|
||||
amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_COMMON);
|
||||
if (unlikely(!cmn_block)) {
|
||||
dev_err(adev->dev, "Failed to get BIF handle\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
r = cmn_block->version->funcs->resume(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Reinit GFXHUB */
|
||||
adev->gfxhub.funcs->init(adev);
|
||||
r = adev->gfxhub.funcs->gart_enable(adev);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "GFXHUB gart reenable failed after reset\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Reload GFX firmware */
|
||||
r = psp_load_fw_list(&adev->psp, ucode_list, ucode_count);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "GFX ucode load failed after reset\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Resume RLC, FW needs RLC alive to complete reset process */
|
||||
adev->gfx.rlc.funcs->resume(adev);
|
||||
|
||||
/* Wait for FW reset event complete */
|
||||
r = smu_wait_for_event(adev, SMU_EVENT_RESET_COMPLETE, 0);
|
||||
if (r) {
|
||||
dev_err(adev->dev,
|
||||
"Failed to get response from firmware after reset\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
for (i = 0; i < adev->num_ip_blocks; i++) {
|
||||
if (!(adev->ip_blocks[i].version->type ==
|
||||
AMD_IP_BLOCK_TYPE_GFX ||
|
||||
adev->ip_blocks[i].version->type ==
|
||||
AMD_IP_BLOCK_TYPE_SDMA))
|
||||
continue;
|
||||
r = adev->ip_blocks[i].version->funcs->resume(adev);
|
||||
if (r) {
|
||||
dev_err(adev->dev,
|
||||
"resume of IP block <%s> failed %d\n",
|
||||
adev->ip_blocks[i].version->funcs->name, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
adev->ip_blocks[i].status.hw = true;
|
||||
}
|
||||
|
||||
for (i = 0; i < adev->num_ip_blocks; i++) {
|
||||
if (!(adev->ip_blocks[i].version->type ==
|
||||
AMD_IP_BLOCK_TYPE_GFX ||
|
||||
adev->ip_blocks[i].version->type ==
|
||||
AMD_IP_BLOCK_TYPE_SDMA ||
|
||||
adev->ip_blocks[i].version->type ==
|
||||
AMD_IP_BLOCK_TYPE_COMMON))
|
||||
continue;
|
||||
|
||||
if (adev->ip_blocks[i].version->funcs->late_init) {
|
||||
r = adev->ip_blocks[i].version->funcs->late_init(
|
||||
(void *)adev);
|
||||
if (r) {
|
||||
dev_err(adev->dev,
|
||||
"late_init of IP block <%s> failed %d after reset\n",
|
||||
adev->ip_blocks[i].version->funcs->name,
|
||||
r);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
adev->ip_blocks[i].status.late_initialized = true;
|
||||
}
|
||||
|
||||
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_GATE);
|
||||
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_GATE);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int
|
||||
aldebaran_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
|
||||
struct amdgpu_reset_context *reset_context)
|
||||
{
|
||||
int r;
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
|
||||
if (reset_context->hive == NULL) {
|
||||
/* Wrong context, return error */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
list_for_each_entry(tmp_adev, &reset_context->hive->device_list,
|
||||
gmc.xgmi.head) {
|
||||
dev_info(tmp_adev->dev,
|
||||
"GPU reset succeeded, trying to resume\n");
|
||||
r = aldebaran_mode2_restore_ip(tmp_adev);
|
||||
if (r)
|
||||
goto end;
|
||||
|
||||
/*
|
||||
* Add this ASIC as tracked as reset was already
|
||||
* complete successfully.
|
||||
*/
|
||||
amdgpu_register_gpu_instance(tmp_adev);
|
||||
|
||||
/* Resume RAS */
|
||||
amdgpu_ras_resume(tmp_adev);
|
||||
|
||||
/* Update PSP FW topology after reset */
|
||||
if (reset_context->hive &&
|
||||
tmp_adev->gmc.xgmi.num_physical_nodes > 1)
|
||||
r = amdgpu_xgmi_update_topology(reset_context->hive,
|
||||
tmp_adev);
|
||||
|
||||
if (!r) {
|
||||
amdgpu_irq_gpu_reset_resume_helper(tmp_adev);
|
||||
|
||||
r = amdgpu_ib_ring_tests(tmp_adev);
|
||||
if (r) {
|
||||
dev_err(tmp_adev->dev,
|
||||
"ib ring test failed (%d).\n", r);
|
||||
r = -EAGAIN;
|
||||
tmp_adev->asic_reset_res = r;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct amdgpu_reset_handler aldebaran_mode2_handler = {
|
||||
.reset_method = AMD_RESET_METHOD_MODE2,
|
||||
.prepare_env = NULL,
|
||||
.prepare_hwcontext = aldebaran_mode2_prepare_hwcontext,
|
||||
.perform_reset = aldebaran_mode2_perform_reset,
|
||||
.restore_hwcontext = aldebaran_mode2_restore_hwcontext,
|
||||
.restore_env = NULL,
|
||||
.do_reset = aldebaran_mode2_reset,
|
||||
};
|
||||
|
||||
int aldebaran_reset_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_reset_control *reset_ctl;
|
||||
|
||||
reset_ctl = kzalloc(sizeof(*reset_ctl), GFP_KERNEL);
|
||||
if (!reset_ctl)
|
||||
return -ENOMEM;
|
||||
|
||||
reset_ctl->handle = adev;
|
||||
reset_ctl->async_reset = aldebaran_async_reset;
|
||||
reset_ctl->active_reset = AMD_RESET_METHOD_NONE;
|
||||
reset_ctl->get_reset_handler = aldebaran_get_reset_handler;
|
||||
|
||||
INIT_LIST_HEAD(&reset_ctl->reset_handlers);
|
||||
INIT_WORK(&reset_ctl->reset_work, reset_ctl->async_reset);
|
||||
/* Only mode2 is handled through reset control now */
|
||||
amdgpu_reset_add_handler(reset_ctl, &aldebaran_mode2_handler);
|
||||
|
||||
adev->reset_cntl = reset_ctl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aldebaran_reset_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
kfree(adev->reset_cntl);
|
||||
adev->reset_cntl = NULL;
|
||||
return 0;
|
||||
}
|
32
drivers/gpu/drm/amd/amdgpu/aldebaran.h
Normal file
32
drivers/gpu/drm/amd/amdgpu/aldebaran.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2021 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ALDEBARAN_H__
|
||||
#define __ALDEBARAN_H__
|
||||
|
||||
#include "amdgpu.h"
|
||||
|
||||
int aldebaran_reset_init(struct amdgpu_device *adev);
|
||||
int aldebaran_reset_fini(struct amdgpu_device *adev);
|
||||
|
||||
#endif
|
@ -107,7 +107,6 @@
|
||||
#include "amdgpu_gfxhub.h"
|
||||
#include "amdgpu_df.h"
|
||||
#include "amdgpu_smuio.h"
|
||||
#include "amdgpu_hdp.h"
|
||||
|
||||
#define MAX_GPU_INSTANCE 16
|
||||
|
||||
@ -271,6 +270,8 @@ struct amdgpu_bo_va_mapping;
|
||||
struct amdgpu_atif;
|
||||
struct kfd_vm_fault_info;
|
||||
struct amdgpu_hive_info;
|
||||
struct amdgpu_reset_context;
|
||||
struct amdgpu_reset_control;
|
||||
|
||||
enum amdgpu_cp_irq {
|
||||
AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP = 0,
|
||||
@ -589,6 +590,7 @@ struct amdgpu_allowed_register_entry {
|
||||
};
|
||||
|
||||
enum amd_reset_method {
|
||||
AMD_RESET_METHOD_NONE = -1,
|
||||
AMD_RESET_METHOD_LEGACY = 0,
|
||||
AMD_RESET_METHOD_MODE0,
|
||||
AMD_RESET_METHOD_MODE1,
|
||||
@ -920,6 +922,7 @@ struct amdgpu_device {
|
||||
struct amdgpu_irq_src pageflip_irq;
|
||||
struct amdgpu_irq_src hpd_irq;
|
||||
struct amdgpu_irq_src dmub_trace_irq;
|
||||
struct amdgpu_irq_src dmub_outbox_irq;
|
||||
|
||||
/* rings */
|
||||
u64 fence_context;
|
||||
@ -1030,13 +1033,9 @@ struct amdgpu_device {
|
||||
|
||||
/* s3/s4 mask */
|
||||
bool in_suspend;
|
||||
bool in_hibernate;
|
||||
|
||||
/*
|
||||
* The combination flag in_poweroff_reboot_com used to identify the poweroff
|
||||
* and reboot opt in the s0i3 system-wide suspend.
|
||||
*/
|
||||
bool in_poweroff_reboot_com;
|
||||
bool in_s3;
|
||||
bool in_s4;
|
||||
bool in_s0ix;
|
||||
|
||||
atomic_t in_gpu_reset;
|
||||
enum pp_mp1_state mp1_state;
|
||||
@ -1078,6 +1077,8 @@ struct amdgpu_device {
|
||||
|
||||
bool in_pci_err_recovery;
|
||||
struct pci_saved_state *pci_state;
|
||||
|
||||
struct amdgpu_reset_control *reset_cntl;
|
||||
};
|
||||
|
||||
static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev)
|
||||
@ -1129,13 +1130,10 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type);
|
||||
bool amdgpu_device_has_dc_support(struct amdgpu_device *adev);
|
||||
|
||||
int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
|
||||
struct amdgpu_job *job,
|
||||
bool *need_full_reset_arg);
|
||||
struct amdgpu_reset_context *reset_context);
|
||||
|
||||
int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive,
|
||||
struct list_head *device_list_handle,
|
||||
bool *need_full_reset_arg,
|
||||
bool skip_hw_reset);
|
||||
int amdgpu_do_asic_reset(struct list_head *device_list_handle,
|
||||
struct amdgpu_reset_context *reset_context);
|
||||
|
||||
int emu_soc_asic_init(struct amdgpu_device *adev);
|
||||
|
||||
@ -1275,8 +1273,9 @@ void amdgpu_device_program_register_sequence(struct amdgpu_device *adev,
|
||||
const u32 *registers,
|
||||
const u32 array_size);
|
||||
|
||||
bool amdgpu_device_supports_atpx(struct drm_device *dev);
|
||||
int amdgpu_device_mode1_reset(struct amdgpu_device *adev);
|
||||
bool amdgpu_device_supports_atpx(struct drm_device *dev);
|
||||
bool amdgpu_device_supports_px(struct drm_device *dev);
|
||||
bool amdgpu_device_supports_boco(struct drm_device *dev);
|
||||
bool amdgpu_device_supports_baco(struct drm_device *dev);
|
||||
bool amdgpu_device_is_peer_accessible(struct amdgpu_device *adev,
|
||||
@ -1390,6 +1389,13 @@ void amdgpu_pci_resume(struct pci_dev *pdev);
|
||||
bool amdgpu_device_cache_pci_state(struct pci_dev *pdev);
|
||||
bool amdgpu_device_load_pci_state(struct pci_dev *pdev);
|
||||
|
||||
bool amdgpu_device_skip_hw_access(struct amdgpu_device *adev);
|
||||
|
||||
int amdgpu_device_set_cg_state(struct amdgpu_device *adev,
|
||||
enum amd_clockgating_state state);
|
||||
int amdgpu_device_set_pg_state(struct amdgpu_device *adev,
|
||||
enum amd_powergating_state state);
|
||||
|
||||
#include "amdgpu_object.h"
|
||||
|
||||
static inline bool amdgpu_is_tmz(struct amdgpu_device *adev)
|
||||
|
@ -246,6 +246,7 @@ int amdgpu_amdkfd_alloc_gtt_mem(struct kgd_dev *kgd, size_t size,
|
||||
bp.flags = AMDGPU_GEM_CREATE_CPU_GTT_USWC;
|
||||
bp.type = ttm_bo_type_kernel;
|
||||
bp.resv = NULL;
|
||||
bp.bo_ptr_size = sizeof(struct amdgpu_bo);
|
||||
|
||||
if (cp_mqd_gfx9)
|
||||
bp.flags |= AMDGPU_GEM_CREATE_CP_MQD_GFX9;
|
||||
@ -317,6 +318,7 @@ int amdgpu_amdkfd_alloc_gws(struct kgd_dev *kgd, size_t size,
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
|
||||
struct amdgpu_bo *bo = NULL;
|
||||
struct amdgpu_bo_user *ubo;
|
||||
struct amdgpu_bo_param bp;
|
||||
int r;
|
||||
|
||||
@ -327,14 +329,16 @@ int amdgpu_amdkfd_alloc_gws(struct kgd_dev *kgd, size_t size,
|
||||
bp.flags = AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
|
||||
bp.type = ttm_bo_type_device;
|
||||
bp.resv = NULL;
|
||||
bp.bo_ptr_size = sizeof(struct amdgpu_bo);
|
||||
|
||||
r = amdgpu_bo_create(adev, &bp, &bo);
|
||||
r = amdgpu_bo_create_user(adev, &bp, &ubo);
|
||||
if (r) {
|
||||
dev_err(adev->dev,
|
||||
"failed to allocate gws BO for amdkfd (%d)\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
bo = &ubo->bo;
|
||||
*mem_obj = bo;
|
||||
return 0;
|
||||
}
|
||||
@ -495,8 +499,6 @@ int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd,
|
||||
*dma_buf_kgd = (struct kgd_dev *)adev;
|
||||
if (bo_size)
|
||||
*bo_size = amdgpu_bo_size(bo);
|
||||
if (metadata_size)
|
||||
*metadata_size = bo->metadata_size;
|
||||
if (metadata_buffer)
|
||||
r = amdgpu_bo_get_metadata(bo, metadata_buffer, buffer_size,
|
||||
metadata_size, &metadata_flags);
|
||||
|
@ -1232,157 +1232,6 @@ int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device *
|
||||
return amdgpu_atombios_get_max_vddc(adev, VOLTAGE_TYPE_VDDC, leakage_idx, voltage);
|
||||
}
|
||||
|
||||
int amdgpu_atombios_get_leakage_id_from_vbios(struct amdgpu_device *adev,
|
||||
u16 *leakage_id)
|
||||
{
|
||||
union set_voltage args;
|
||||
int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
|
||||
u8 frev, crev;
|
||||
|
||||
if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev, &crev))
|
||||
return -EINVAL;
|
||||
|
||||
switch (crev) {
|
||||
case 3:
|
||||
case 4:
|
||||
args.v3.ucVoltageType = 0;
|
||||
args.v3.ucVoltageMode = ATOM_GET_LEAKAGE_ID;
|
||||
args.v3.usVoltageLevel = 0;
|
||||
|
||||
amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
|
||||
*leakage_id = le16_to_cpu(args.v3.usVoltageLevel);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_atombios_get_leakage_vddc_based_on_leakage_params(struct amdgpu_device *adev,
|
||||
u16 *vddc, u16 *vddci,
|
||||
u16 virtual_voltage_id,
|
||||
u16 vbios_voltage_id)
|
||||
{
|
||||
int index = GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo);
|
||||
u8 frev, crev;
|
||||
u16 data_offset, size;
|
||||
int i, j;
|
||||
ATOM_ASIC_PROFILING_INFO_V2_1 *profile;
|
||||
u16 *leakage_bin, *vddc_id_buf, *vddc_buf, *vddci_id_buf, *vddci_buf;
|
||||
|
||||
*vddc = 0;
|
||||
*vddci = 0;
|
||||
|
||||
if (!amdgpu_atom_parse_data_header(adev->mode_info.atom_context, index, &size,
|
||||
&frev, &crev, &data_offset))
|
||||
return -EINVAL;
|
||||
|
||||
profile = (ATOM_ASIC_PROFILING_INFO_V2_1 *)
|
||||
(adev->mode_info.atom_context->bios + data_offset);
|
||||
|
||||
switch (frev) {
|
||||
case 1:
|
||||
return -EINVAL;
|
||||
case 2:
|
||||
switch (crev) {
|
||||
case 1:
|
||||
if (size < sizeof(ATOM_ASIC_PROFILING_INFO_V2_1))
|
||||
return -EINVAL;
|
||||
leakage_bin = (u16 *)
|
||||
(adev->mode_info.atom_context->bios + data_offset +
|
||||
le16_to_cpu(profile->usLeakageBinArrayOffset));
|
||||
vddc_id_buf = (u16 *)
|
||||
(adev->mode_info.atom_context->bios + data_offset +
|
||||
le16_to_cpu(profile->usElbVDDC_IdArrayOffset));
|
||||
vddc_buf = (u16 *)
|
||||
(adev->mode_info.atom_context->bios + data_offset +
|
||||
le16_to_cpu(profile->usElbVDDC_LevelArrayOffset));
|
||||
vddci_id_buf = (u16 *)
|
||||
(adev->mode_info.atom_context->bios + data_offset +
|
||||
le16_to_cpu(profile->usElbVDDCI_IdArrayOffset));
|
||||
vddci_buf = (u16 *)
|
||||
(adev->mode_info.atom_context->bios + data_offset +
|
||||
le16_to_cpu(profile->usElbVDDCI_LevelArrayOffset));
|
||||
|
||||
if (profile->ucElbVDDC_Num > 0) {
|
||||
for (i = 0; i < profile->ucElbVDDC_Num; i++) {
|
||||
if (vddc_id_buf[i] == virtual_voltage_id) {
|
||||
for (j = 0; j < profile->ucLeakageBinNum; j++) {
|
||||
if (vbios_voltage_id <= leakage_bin[j]) {
|
||||
*vddc = vddc_buf[j * profile->ucElbVDDC_Num + i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (profile->ucElbVDDCI_Num > 0) {
|
||||
for (i = 0; i < profile->ucElbVDDCI_Num; i++) {
|
||||
if (vddci_id_buf[i] == virtual_voltage_id) {
|
||||
for (j = 0; j < profile->ucLeakageBinNum; j++) {
|
||||
if (vbios_voltage_id <= leakage_bin[j]) {
|
||||
*vddci = vddci_buf[j * profile->ucElbVDDCI_Num + i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
union get_voltage_info {
|
||||
struct _GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_2 in;
|
||||
struct _GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2 evv_out;
|
||||
};
|
||||
|
||||
int amdgpu_atombios_get_voltage_evv(struct amdgpu_device *adev,
|
||||
u16 virtual_voltage_id,
|
||||
u16 *voltage)
|
||||
{
|
||||
int index = GetIndexIntoMasterTable(COMMAND, GetVoltageInfo);
|
||||
u32 entry_id;
|
||||
u32 count = adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count;
|
||||
union get_voltage_info args;
|
||||
|
||||
for (entry_id = 0; entry_id < count; entry_id++) {
|
||||
if (adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[entry_id].v ==
|
||||
virtual_voltage_id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (entry_id >= count)
|
||||
return -EINVAL;
|
||||
|
||||
args.in.ucVoltageType = VOLTAGE_TYPE_VDDC;
|
||||
args.in.ucVoltageMode = ATOM_GET_VOLTAGE_EVV_VOLTAGE;
|
||||
args.in.usVoltageLevel = cpu_to_le16(virtual_voltage_id);
|
||||
args.in.ulSCLKFreq =
|
||||
cpu_to_le32(adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[entry_id].clk);
|
||||
|
||||
amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
|
||||
*voltage = le16_to_cpu(args.evv_out.usVoltageLevel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
union voltage_object_info {
|
||||
struct _ATOM_VOLTAGE_OBJECT_INFO v1;
|
||||
struct _ATOM_VOLTAGE_OBJECT_INFO_V2 v2;
|
||||
@ -1913,7 +1762,7 @@ static ssize_t amdgpu_atombios_get_vbios_version(struct device *dev,
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
struct atom_context *ctx = adev->mode_info.atom_context;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", ctx->vbios_version);
|
||||
return sysfs_emit(buf, "%s\n", ctx->vbios_version);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(vbios_version, 0444, amdgpu_atombios_get_vbios_version,
|
||||
|
@ -168,18 +168,6 @@ int amdgpu_atombios_get_memory_pll_dividers(struct amdgpu_device *adev,
|
||||
void amdgpu_atombios_set_engine_dram_timings(struct amdgpu_device *adev,
|
||||
u32 eng_clock, u32 mem_clock);
|
||||
|
||||
int amdgpu_atombios_get_leakage_id_from_vbios(struct amdgpu_device *adev,
|
||||
u16 *leakage_id);
|
||||
|
||||
int amdgpu_atombios_get_leakage_vddc_based_on_leakage_params(struct amdgpu_device *adev,
|
||||
u16 *vddc, u16 *vddci,
|
||||
u16 virtual_voltage_id,
|
||||
u16 vbios_voltage_id);
|
||||
|
||||
int amdgpu_atombios_get_voltage_evv(struct amdgpu_device *adev,
|
||||
u16 virtual_voltage_id,
|
||||
u16 *voltage);
|
||||
|
||||
bool
|
||||
amdgpu_atombios_is_voltage_gpio(struct amdgpu_device *adev,
|
||||
u8 voltage_type, u8 voltage_mode);
|
||||
|
@ -85,6 +85,8 @@ static void amdgpu_benchmark_move(struct amdgpu_device *adev, unsigned size,
|
||||
bp.flags = 0;
|
||||
bp.type = ttm_bo_type_kernel;
|
||||
bp.resv = NULL;
|
||||
bp.bo_ptr_size = sizeof(struct amdgpu_bo);
|
||||
|
||||
n = AMDGPU_BENCHMARK_ITERATIONS;
|
||||
r = amdgpu_bo_create(adev, &bp, &sobj);
|
||||
if (r) {
|
||||
|
@ -65,6 +65,7 @@
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_pmu.h"
|
||||
#include "amdgpu_fru_eeprom.h"
|
||||
#include "amdgpu_reset.h"
|
||||
|
||||
#include <linux/suspend.h>
|
||||
#include <drm/task_barrier.h>
|
||||
@ -137,7 +138,7 @@ static ssize_t amdgpu_device_get_pcie_replay_count(struct device *dev,
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
uint64_t cnt = amdgpu_asic_get_pcie_replay_count(adev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%llu\n", cnt);
|
||||
return sysfs_emit(buf, "%llu\n", cnt);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(pcie_replay_count, S_IRUGO,
|
||||
@ -161,7 +162,7 @@ static ssize_t amdgpu_device_get_product_name(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", adev->product_name);
|
||||
return sysfs_emit(buf, "%s\n", adev->product_name);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(product_name, S_IRUGO,
|
||||
@ -183,7 +184,7 @@ static ssize_t amdgpu_device_get_product_number(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", adev->product_number);
|
||||
return sysfs_emit(buf, "%s\n", adev->product_number);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(product_number, S_IRUGO,
|
||||
@ -205,25 +206,25 @@ static ssize_t amdgpu_device_get_serial_number(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", adev->serial);
|
||||
return sysfs_emit(buf, "%s\n", adev->serial);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(serial_number, S_IRUGO,
|
||||
amdgpu_device_get_serial_number, NULL);
|
||||
|
||||
/**
|
||||
* amdgpu_device_supports_atpx - Is the device a dGPU with HG/PX power control
|
||||
* amdgpu_device_supports_px - Is the device a dGPU with ATPX power control
|
||||
*
|
||||
* @dev: drm_device pointer
|
||||
*
|
||||
* Returns true if the device is a dGPU with HG/PX power control,
|
||||
* Returns true if the device is a dGPU with ATPX power control,
|
||||
* otherwise return false.
|
||||
*/
|
||||
bool amdgpu_device_supports_atpx(struct drm_device *dev)
|
||||
bool amdgpu_device_supports_px(struct drm_device *dev)
|
||||
{
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
|
||||
if (adev->flags & AMD_IS_PX)
|
||||
if ((adev->flags & AMD_IS_PX) && !amdgpu_is_atpx_hybrid())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@ -233,14 +234,15 @@ bool amdgpu_device_supports_atpx(struct drm_device *dev)
|
||||
*
|
||||
* @dev: drm_device pointer
|
||||
*
|
||||
* Returns true if the device is a dGPU with HG/PX power control,
|
||||
* Returns true if the device is a dGPU with ACPI power control,
|
||||
* otherwise return false.
|
||||
*/
|
||||
bool amdgpu_device_supports_boco(struct drm_device *dev)
|
||||
{
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
|
||||
if (adev->has_pr3)
|
||||
if (adev->has_pr3 ||
|
||||
((adev->flags & AMD_IS_PX) && amdgpu_is_atpx_hybrid()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@ -326,6 +328,35 @@ void amdgpu_device_vram_access(struct amdgpu_device *adev, loff_t pos,
|
||||
/*
|
||||
* register access helper functions.
|
||||
*/
|
||||
|
||||
/* Check if hw access should be skipped because of hotplug or device error */
|
||||
bool amdgpu_device_skip_hw_access(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->in_pci_err_recovery)
|
||||
return true;
|
||||
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
/*
|
||||
* This is a bit complicated to understand, so worth a comment. What we assert
|
||||
* here is that the GPU reset is not running on another thread in parallel.
|
||||
*
|
||||
* For this we trylock the read side of the reset semaphore, if that succeeds
|
||||
* we know that the reset is not running in paralell.
|
||||
*
|
||||
* If the trylock fails we assert that we are either already holding the read
|
||||
* side of the lock or are the reset thread itself and hold the write side of
|
||||
* the lock.
|
||||
*/
|
||||
if (in_task()) {
|
||||
if (down_read_trylock(&adev->reset_sem))
|
||||
up_read(&adev->reset_sem);
|
||||
else
|
||||
lockdep_assert_held(&adev->reset_sem);
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_rreg - read a memory mapped IO or indirect register
|
||||
*
|
||||
@ -340,7 +371,7 @@ uint32_t amdgpu_device_rreg(struct amdgpu_device *adev,
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
if (adev->in_pci_err_recovery)
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
return 0;
|
||||
|
||||
if ((reg * 4) < adev->rmmio_size) {
|
||||
@ -377,7 +408,7 @@ uint32_t amdgpu_device_rreg(struct amdgpu_device *adev,
|
||||
*/
|
||||
uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset)
|
||||
{
|
||||
if (adev->in_pci_err_recovery)
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
return 0;
|
||||
|
||||
if (offset < adev->rmmio_size)
|
||||
@ -402,7 +433,7 @@ uint8_t amdgpu_mm_rreg8(struct amdgpu_device *adev, uint32_t offset)
|
||||
*/
|
||||
void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value)
|
||||
{
|
||||
if (adev->in_pci_err_recovery)
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
return;
|
||||
|
||||
if (offset < adev->rmmio_size)
|
||||
@ -425,7 +456,7 @@ void amdgpu_device_wreg(struct amdgpu_device *adev,
|
||||
uint32_t reg, uint32_t v,
|
||||
uint32_t acc_flags)
|
||||
{
|
||||
if (adev->in_pci_err_recovery)
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
return;
|
||||
|
||||
if ((reg * 4) < adev->rmmio_size) {
|
||||
@ -452,14 +483,14 @@ void amdgpu_device_wreg(struct amdgpu_device *adev,
|
||||
void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
|
||||
uint32_t reg, uint32_t v)
|
||||
{
|
||||
if (adev->in_pci_err_recovery)
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
return;
|
||||
|
||||
if (amdgpu_sriov_fullaccess(adev) &&
|
||||
adev->gfx.rlc.funcs &&
|
||||
adev->gfx.rlc.funcs->is_rlcg_access_range) {
|
||||
if (adev->gfx.rlc.funcs->is_rlcg_access_range(adev, reg))
|
||||
return adev->gfx.rlc.funcs->rlcg_wreg(adev, reg, v);
|
||||
return adev->gfx.rlc.funcs->rlcg_wreg(adev, reg, v, 0);
|
||||
} else {
|
||||
writel(v, ((void __iomem *)adev->rmmio) + (reg * 4));
|
||||
}
|
||||
@ -476,7 +507,7 @@ void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
|
||||
*/
|
||||
u32 amdgpu_mm_rdoorbell(struct amdgpu_device *adev, u32 index)
|
||||
{
|
||||
if (adev->in_pci_err_recovery)
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
return 0;
|
||||
|
||||
if (index < adev->doorbell.num_doorbells) {
|
||||
@ -499,7 +530,7 @@ u32 amdgpu_mm_rdoorbell(struct amdgpu_device *adev, u32 index)
|
||||
*/
|
||||
void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v)
|
||||
{
|
||||
if (adev->in_pci_err_recovery)
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
return;
|
||||
|
||||
if (index < adev->doorbell.num_doorbells) {
|
||||
@ -520,7 +551,7 @@ void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v)
|
||||
*/
|
||||
u64 amdgpu_mm_rdoorbell64(struct amdgpu_device *adev, u32 index)
|
||||
{
|
||||
if (adev->in_pci_err_recovery)
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
return 0;
|
||||
|
||||
if (index < adev->doorbell.num_doorbells) {
|
||||
@ -543,7 +574,7 @@ u64 amdgpu_mm_rdoorbell64(struct amdgpu_device *adev, u32 index)
|
||||
*/
|
||||
void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v)
|
||||
{
|
||||
if (adev->in_pci_err_recovery)
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
return;
|
||||
|
||||
if (index < adev->doorbell.num_doorbells) {
|
||||
@ -1391,7 +1422,7 @@ static void amdgpu_switcheroo_set_state(struct pci_dev *pdev,
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
int r;
|
||||
|
||||
if (amdgpu_device_supports_atpx(dev) && state == VGA_SWITCHEROO_OFF)
|
||||
if (amdgpu_device_supports_px(dev) && state == VGA_SWITCHEROO_OFF)
|
||||
return;
|
||||
|
||||
if (state == VGA_SWITCHEROO_ON) {
|
||||
@ -2049,6 +2080,11 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
|
||||
amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_INIT_FAIL, 0, 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*get pf2vf msg info at it's earliest time*/
|
||||
if (amdgpu_sriov_vf(adev))
|
||||
amdgpu_virt_init_data_exchange(adev);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -2331,8 +2367,8 @@ static bool amdgpu_device_check_vram_lost(struct amdgpu_device *adev)
|
||||
* Returns 0 on success, negative error code on failure.
|
||||
*/
|
||||
|
||||
static int amdgpu_device_set_cg_state(struct amdgpu_device *adev,
|
||||
enum amd_clockgating_state state)
|
||||
int amdgpu_device_set_cg_state(struct amdgpu_device *adev,
|
||||
enum amd_clockgating_state state)
|
||||
{
|
||||
int i, j, r;
|
||||
|
||||
@ -2343,6 +2379,10 @@ static int amdgpu_device_set_cg_state(struct amdgpu_device *adev,
|
||||
i = state == AMD_CG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
|
||||
if (!adev->ip_blocks[i].status.late_initialized)
|
||||
continue;
|
||||
/* skip CG for GFX on S0ix */
|
||||
if (adev->in_s0ix &&
|
||||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX)
|
||||
continue;
|
||||
/* skip CG for VCE/UVD, it's handled specially */
|
||||
if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
|
||||
adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE &&
|
||||
@ -2363,7 +2403,8 @@ static int amdgpu_device_set_cg_state(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_device_set_pg_state(struct amdgpu_device *adev, enum amd_powergating_state state)
|
||||
int amdgpu_device_set_pg_state(struct amdgpu_device *adev,
|
||||
enum amd_powergating_state state)
|
||||
{
|
||||
int i, j, r;
|
||||
|
||||
@ -2374,6 +2415,10 @@ static int amdgpu_device_set_pg_state(struct amdgpu_device *adev, enum amd_power
|
||||
i = state == AMD_PG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
|
||||
if (!adev->ip_blocks[i].status.late_initialized)
|
||||
continue;
|
||||
/* skip PG for GFX on S0ix */
|
||||
if (adev->in_s0ix &&
|
||||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX)
|
||||
continue;
|
||||
/* skip CG for VCE/UVD, it's handled specially */
|
||||
if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
|
||||
adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE &&
|
||||
@ -2655,11 +2700,8 @@ static int amdgpu_device_ip_suspend_phase1(struct amdgpu_device *adev)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
if (adev->in_poweroff_reboot_com ||
|
||||
!amdgpu_acpi_is_s0ix_supported(adev) || amdgpu_in_reset(adev)) {
|
||||
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
|
||||
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
|
||||
}
|
||||
amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
|
||||
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
|
||||
|
||||
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
|
||||
if (!adev->ip_blocks[i].status.valid)
|
||||
@ -2699,6 +2741,9 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
if (adev->in_s0ix)
|
||||
amdgpu_gfx_state_change_set(adev, sGpuChangeState_D3Entry);
|
||||
|
||||
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
|
||||
if (!adev->ip_blocks[i].status.valid)
|
||||
continue;
|
||||
@ -2721,6 +2766,17 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev)
|
||||
adev->ip_blocks[i].status.hw = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* skip suspend of gfx and psp for S0ix
|
||||
* gfx is in gfxoff state, so on resume it will exit gfxoff just
|
||||
* like at runtime. PSP is also part of the always on hardware
|
||||
* so no need to suspend it.
|
||||
*/
|
||||
if (adev->in_s0ix &&
|
||||
(adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP ||
|
||||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX))
|
||||
continue;
|
||||
|
||||
/* XXX handle errors */
|
||||
r = adev->ip_blocks[i].version->funcs->suspend(adev);
|
||||
/* XXX handle errors */
|
||||
@ -3086,8 +3142,9 @@ static void amdgpu_device_xgmi_reset_func(struct work_struct *__work)
|
||||
if (adev->asic_reset_res)
|
||||
goto fail;
|
||||
|
||||
if (adev->mmhub.funcs && adev->mmhub.funcs->reset_ras_error_count)
|
||||
adev->mmhub.funcs->reset_ras_error_count(adev);
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->reset_ras_error_count)
|
||||
adev->mmhub.ras_funcs->reset_ras_error_count(adev);
|
||||
} else {
|
||||
|
||||
task_barrier_full(&hive->tb);
|
||||
@ -3197,7 +3254,7 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
struct drm_device *ddev = adev_to_drm(adev);
|
||||
struct pci_dev *pdev = adev->pdev;
|
||||
int r, i;
|
||||
bool atpx = false;
|
||||
bool px = false;
|
||||
u32 max_MBps;
|
||||
|
||||
adev->shutdown = false;
|
||||
@ -3359,16 +3416,12 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
|
||||
vga_client_register(adev->pdev, adev, NULL, amdgpu_device_vga_set_decode);
|
||||
|
||||
if (amdgpu_device_supports_atpx(ddev))
|
||||
atpx = true;
|
||||
if (amdgpu_has_atpx() &&
|
||||
(amdgpu_is_atpx_hybrid() ||
|
||||
amdgpu_has_atpx_dgpu_power_cntl()) &&
|
||||
!pci_is_thunderbolt_attached(adev->pdev))
|
||||
if (amdgpu_device_supports_px(ddev)) {
|
||||
px = true;
|
||||
vga_switcheroo_register_client(adev->pdev,
|
||||
&amdgpu_switcheroo_ops, atpx);
|
||||
if (atpx)
|
||||
&amdgpu_switcheroo_ops, px);
|
||||
vga_switcheroo_init_domain_pm_ops(adev->dev, &adev->vga_pm_domain);
|
||||
}
|
||||
|
||||
if (amdgpu_emu_mode == 1) {
|
||||
/* post the asic on emulation mode */
|
||||
@ -3376,6 +3429,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
||||
goto fence_driver_init;
|
||||
}
|
||||
|
||||
amdgpu_reset_init(adev);
|
||||
|
||||
/* detect if we are with an SRIOV vbios */
|
||||
amdgpu_device_detect_sriov_bios(adev);
|
||||
|
||||
@ -3575,7 +3630,7 @@ release_ras_con:
|
||||
|
||||
failed:
|
||||
amdgpu_vf_error_trans_all(adev);
|
||||
if (atpx)
|
||||
if (px)
|
||||
vga_switcheroo_fini_domain_pm_ops(adev->dev);
|
||||
|
||||
failed_unmap:
|
||||
@ -3626,6 +3681,9 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
|
||||
release_firmware(adev->firmware.gpu_info_fw);
|
||||
adev->firmware.gpu_info_fw = NULL;
|
||||
adev->accel_working = false;
|
||||
|
||||
amdgpu_reset_fini(adev);
|
||||
|
||||
/* free i2c buses */
|
||||
if (!amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_i2c_fini(adev);
|
||||
@ -3635,13 +3693,10 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
|
||||
|
||||
kfree(adev->bios);
|
||||
adev->bios = NULL;
|
||||
if (amdgpu_has_atpx() &&
|
||||
(amdgpu_is_atpx_hybrid() ||
|
||||
amdgpu_has_atpx_dgpu_power_cntl()) &&
|
||||
!pci_is_thunderbolt_attached(adev->pdev))
|
||||
if (amdgpu_device_supports_px(adev_to_drm(adev))) {
|
||||
vga_switcheroo_unregister_client(adev->pdev);
|
||||
if (amdgpu_device_supports_atpx(adev_to_drm(adev)))
|
||||
vga_switcheroo_fini_domain_pm_ops(adev->dev);
|
||||
}
|
||||
if ((adev->pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
|
||||
vga_client_register(adev->pdev, NULL, NULL, NULL);
|
||||
iounmap(adev->rmmio);
|
||||
@ -3674,14 +3729,9 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
|
||||
*/
|
||||
int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter iter;
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
int r;
|
||||
|
||||
adev = drm_to_adev(dev);
|
||||
|
||||
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||
return 0;
|
||||
|
||||
@ -3693,61 +3743,19 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
|
||||
|
||||
cancel_delayed_work_sync(&adev->delayed_init_work);
|
||||
|
||||
if (!amdgpu_device_has_dc_support(adev)) {
|
||||
/* turn off display hw */
|
||||
drm_modeset_lock_all(dev);
|
||||
drm_connector_list_iter_begin(dev, &iter);
|
||||
drm_for_each_connector_iter(connector, &iter)
|
||||
drm_helper_connector_dpms(connector,
|
||||
DRM_MODE_DPMS_OFF);
|
||||
drm_connector_list_iter_end(&iter);
|
||||
drm_modeset_unlock_all(dev);
|
||||
/* 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 drm_framebuffer *fb = crtc->primary->fb;
|
||||
struct amdgpu_bo *robj;
|
||||
|
||||
if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
|
||||
struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
|
||||
r = amdgpu_bo_reserve(aobj, true);
|
||||
if (r == 0) {
|
||||
amdgpu_bo_unpin(aobj);
|
||||
amdgpu_bo_unreserve(aobj);
|
||||
}
|
||||
}
|
||||
|
||||
if (fb == NULL || fb->obj[0] == NULL) {
|
||||
continue;
|
||||
}
|
||||
robj = gem_to_amdgpu_bo(fb->obj[0]);
|
||||
/* don't unpin kernel fb objects */
|
||||
if (!amdgpu_fbdev_robj_is_fb(adev, robj)) {
|
||||
r = amdgpu_bo_reserve(robj, true);
|
||||
if (r == 0) {
|
||||
amdgpu_bo_unpin(robj);
|
||||
amdgpu_bo_unreserve(robj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
amdgpu_ras_suspend(adev);
|
||||
|
||||
r = amdgpu_device_ip_suspend_phase1(adev);
|
||||
|
||||
amdgpu_amdkfd_suspend(adev, adev->in_runpm);
|
||||
if (!adev->in_s0ix)
|
||||
amdgpu_amdkfd_suspend(adev, adev->in_runpm);
|
||||
|
||||
/* evict vram memory */
|
||||
amdgpu_bo_evict_vram(adev);
|
||||
|
||||
amdgpu_fence_driver_suspend(adev);
|
||||
|
||||
if (adev->in_poweroff_reboot_com ||
|
||||
!amdgpu_acpi_is_s0ix_supported(adev) || amdgpu_in_reset(adev))
|
||||
r = amdgpu_device_ip_suspend_phase2(adev);
|
||||
else
|
||||
amdgpu_gfx_state_change_set(adev, sGpuChangeState_D3Entry);
|
||||
r = amdgpu_device_ip_suspend_phase2(adev);
|
||||
/* evict remaining vram memory
|
||||
* This second call to evict vram is to evict the gart page table
|
||||
* using the CPU.
|
||||
@ -3769,16 +3777,13 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon)
|
||||
*/
|
||||
int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter iter;
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
struct drm_crtc *crtc;
|
||||
int r = 0;
|
||||
|
||||
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||
return 0;
|
||||
|
||||
if (amdgpu_acpi_is_s0ix_supported(adev))
|
||||
if (adev->in_s0ix)
|
||||
amdgpu_gfx_state_change_set(adev, sGpuChangeState_D0Entry);
|
||||
|
||||
/* post card */
|
||||
@ -3803,50 +3808,17 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
|
||||
queue_delayed_work(system_wq, &adev->delayed_init_work,
|
||||
msecs_to_jiffies(AMDGPU_RESUME_MS));
|
||||
|
||||
if (!amdgpu_device_has_dc_support(adev)) {
|
||||
/* 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 && !adev->enable_virtual_display) {
|
||||
struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
|
||||
r = amdgpu_bo_reserve(aobj, true);
|
||||
if (r == 0) {
|
||||
r = amdgpu_bo_pin(aobj, AMDGPU_GEM_DOMAIN_VRAM);
|
||||
if (r != 0)
|
||||
dev_err(adev->dev, "Failed to pin cursor BO (%d)\n", r);
|
||||
amdgpu_crtc->cursor_addr = amdgpu_bo_gpu_offset(aobj);
|
||||
amdgpu_bo_unreserve(aobj);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!adev->in_s0ix) {
|
||||
r = amdgpu_amdkfd_resume(adev, adev->in_runpm);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
r = amdgpu_amdkfd_resume(adev, adev->in_runpm);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* Make sure IB tests flushed */
|
||||
flush_delayed_work(&adev->delayed_init_work);
|
||||
|
||||
/* blat the mode back in */
|
||||
if (fbcon) {
|
||||
if (!amdgpu_device_has_dc_support(adev)) {
|
||||
/* pre DCE11 */
|
||||
drm_helper_resume_force_mode(dev);
|
||||
|
||||
/* turn on display hw */
|
||||
drm_modeset_lock_all(dev);
|
||||
|
||||
drm_connector_list_iter_begin(dev, &iter);
|
||||
drm_for_each_connector_iter(connector, &iter)
|
||||
drm_helper_connector_dpms(connector,
|
||||
DRM_MODE_DPMS_ON);
|
||||
drm_connector_list_iter_end(&iter);
|
||||
|
||||
drm_modeset_unlock_all(dev);
|
||||
}
|
||||
if (fbcon)
|
||||
amdgpu_fbdev_set_suspend(adev, 0);
|
||||
}
|
||||
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
|
||||
@ -4144,11 +4116,11 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
|
||||
amdgpu_amdkfd_post_reset(adev);
|
||||
|
||||
error:
|
||||
amdgpu_virt_release_full_gpu(adev, true);
|
||||
if (!r && adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST) {
|
||||
amdgpu_inc_vram_lost(adev);
|
||||
r = amdgpu_device_recover_vram(adev);
|
||||
}
|
||||
amdgpu_virt_release_full_gpu(adev, true);
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -4225,6 +4197,8 @@ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev)
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
case CHIP_NAVY_FLOUNDER:
|
||||
case CHIP_DIMGREY_CAVEFISH:
|
||||
case CHIP_VANGOGH:
|
||||
case CHIP_ALDEBARAN:
|
||||
break;
|
||||
default:
|
||||
goto disabled;
|
||||
@ -4279,11 +4253,15 @@ int amdgpu_device_mode1_reset(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
|
||||
struct amdgpu_job *job,
|
||||
bool *need_full_reset_arg)
|
||||
struct amdgpu_reset_context *reset_context)
|
||||
{
|
||||
int i, r = 0;
|
||||
bool need_full_reset = *need_full_reset_arg;
|
||||
struct amdgpu_job *job = NULL;
|
||||
bool need_full_reset =
|
||||
test_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
|
||||
|
||||
if (reset_context->reset_req_dev == adev)
|
||||
job = reset_context->job;
|
||||
|
||||
/* no need to dump if device is not in good state during probe period */
|
||||
if (!adev->gmc.xgmi.pending_reset)
|
||||
@ -4308,6 +4286,13 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
|
||||
if(job)
|
||||
drm_sched_increase_karma(&job->base);
|
||||
|
||||
r = amdgpu_reset_prepare_hwcontext(adev, reset_context);
|
||||
/* If reset handler not implemented, continue; otherwise return */
|
||||
if (r == -ENOSYS)
|
||||
r = 0;
|
||||
else
|
||||
return r;
|
||||
|
||||
/* Don't suspend on bare metal if we are not going to HW reset the ASIC */
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
|
||||
@ -4326,22 +4311,38 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
|
||||
|
||||
if (need_full_reset)
|
||||
r = amdgpu_device_ip_suspend(adev);
|
||||
|
||||
*need_full_reset_arg = need_full_reset;
|
||||
if (need_full_reset)
|
||||
set_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
|
||||
else
|
||||
clear_bit(AMDGPU_NEED_FULL_RESET,
|
||||
&reset_context->flags);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive,
|
||||
struct list_head *device_list_handle,
|
||||
bool *need_full_reset_arg,
|
||||
bool skip_hw_reset)
|
||||
int amdgpu_do_asic_reset(struct list_head *device_list_handle,
|
||||
struct amdgpu_reset_context *reset_context)
|
||||
{
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
bool need_full_reset = *need_full_reset_arg, vram_lost = false;
|
||||
bool need_full_reset, skip_hw_reset, vram_lost = false;
|
||||
int r = 0;
|
||||
|
||||
/* Try reset handler method first */
|
||||
tmp_adev = list_first_entry(device_list_handle, struct amdgpu_device,
|
||||
reset_list);
|
||||
r = amdgpu_reset_perform_reset(tmp_adev, reset_context);
|
||||
/* If reset handler not implemented, continue; otherwise return */
|
||||
if (r == -ENOSYS)
|
||||
r = 0;
|
||||
else
|
||||
return r;
|
||||
|
||||
/* Reset handler not implemented, use the default method */
|
||||
need_full_reset =
|
||||
test_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
|
||||
skip_hw_reset = test_bit(AMDGPU_SKIP_HW_RESET, &reset_context->flags);
|
||||
|
||||
/*
|
||||
* ASIC reset has to be done on all XGMI hive nodes ASAP
|
||||
* to allow proper links negotiation in FW (within 1 sec)
|
||||
@ -4378,9 +4379,9 @@ int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive,
|
||||
|
||||
if (!r && amdgpu_ras_intr_triggered()) {
|
||||
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
|
||||
if (tmp_adev->mmhub.funcs &&
|
||||
tmp_adev->mmhub.funcs->reset_ras_error_count)
|
||||
tmp_adev->mmhub.funcs->reset_ras_error_count(tmp_adev);
|
||||
if (tmp_adev->mmhub.ras_funcs &&
|
||||
tmp_adev->mmhub.ras_funcs->reset_ras_error_count)
|
||||
tmp_adev->mmhub.ras_funcs->reset_ras_error_count(tmp_adev);
|
||||
}
|
||||
|
||||
amdgpu_ras_intr_cleared();
|
||||
@ -4425,7 +4426,8 @@ int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive,
|
||||
*/
|
||||
amdgpu_register_gpu_instance(tmp_adev);
|
||||
|
||||
if (!hive && tmp_adev->gmc.xgmi.num_physical_nodes > 1)
|
||||
if (!reset_context->hive &&
|
||||
tmp_adev->gmc.xgmi.num_physical_nodes > 1)
|
||||
amdgpu_xgmi_add_device(tmp_adev);
|
||||
|
||||
r = amdgpu_device_ip_late_init(tmp_adev);
|
||||
@ -4453,8 +4455,10 @@ int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive,
|
||||
}
|
||||
|
||||
/* Update PSP FW topology after reset */
|
||||
if (hive && tmp_adev->gmc.xgmi.num_physical_nodes > 1)
|
||||
r = amdgpu_xgmi_update_topology(hive, tmp_adev);
|
||||
if (reset_context->hive &&
|
||||
tmp_adev->gmc.xgmi.num_physical_nodes > 1)
|
||||
r = amdgpu_xgmi_update_topology(
|
||||
reset_context->hive, tmp_adev);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4478,7 +4482,10 @@ out:
|
||||
}
|
||||
|
||||
end:
|
||||
*need_full_reset_arg = need_full_reset;
|
||||
if (need_full_reset)
|
||||
set_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
|
||||
else
|
||||
clear_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -4615,6 +4622,74 @@ static int amdgpu_device_suspend_display_audio(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_device_recheck_guilty_jobs(
|
||||
struct amdgpu_device *adev, struct list_head *device_list_handle,
|
||||
struct amdgpu_reset_context *reset_context)
|
||||
{
|
||||
int i, r = 0;
|
||||
|
||||
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
|
||||
struct amdgpu_ring *ring = adev->rings[i];
|
||||
int ret = 0;
|
||||
struct drm_sched_job *s_job;
|
||||
|
||||
if (!ring || !ring->sched.thread)
|
||||
continue;
|
||||
|
||||
s_job = list_first_entry_or_null(&ring->sched.pending_list,
|
||||
struct drm_sched_job, list);
|
||||
if (s_job == NULL)
|
||||
continue;
|
||||
|
||||
/* clear job's guilty and depend the folowing step to decide the real one */
|
||||
drm_sched_reset_karma(s_job);
|
||||
drm_sched_resubmit_jobs_ext(&ring->sched, 1);
|
||||
|
||||
ret = dma_fence_wait_timeout(s_job->s_fence->parent, false, ring->sched.timeout);
|
||||
if (ret == 0) { /* timeout */
|
||||
DRM_ERROR("Found the real bad job! ring:%s, job_id:%llx\n",
|
||||
ring->sched.name, s_job->id);
|
||||
|
||||
/* set guilty */
|
||||
drm_sched_increase_karma(s_job);
|
||||
retry:
|
||||
/* do hw reset */
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
amdgpu_virt_fini_data_exchange(adev);
|
||||
r = amdgpu_device_reset_sriov(adev, false);
|
||||
if (r)
|
||||
adev->asic_reset_res = r;
|
||||
} else {
|
||||
clear_bit(AMDGPU_SKIP_HW_RESET,
|
||||
&reset_context->flags);
|
||||
r = amdgpu_do_asic_reset(device_list_handle,
|
||||
reset_context);
|
||||
if (r && r == -EAGAIN)
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/*
|
||||
* add reset counter so that the following
|
||||
* resubmitted job could flush vmid
|
||||
*/
|
||||
atomic_inc(&adev->gpu_reset_counter);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* got the hw fence, signal finished fence */
|
||||
atomic_dec(ring->sched.score);
|
||||
dma_fence_get(&s_job->s_fence->finished);
|
||||
dma_fence_signal(&s_job->s_fence->finished);
|
||||
dma_fence_put(&s_job->s_fence->finished);
|
||||
|
||||
/* remove node from list and free the job */
|
||||
spin_lock(&ring->sched.job_list_lock);
|
||||
list_del_init(&s_job->list);
|
||||
spin_unlock(&ring->sched.job_list_lock);
|
||||
ring->sched.ops->free_job(s_job);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_gpu_recover - reset the asic and recover scheduler
|
||||
*
|
||||
@ -4630,13 +4705,16 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
struct amdgpu_job *job)
|
||||
{
|
||||
struct list_head device_list, *device_list_handle = NULL;
|
||||
bool need_full_reset = false;
|
||||
bool job_signaled = false;
|
||||
struct amdgpu_hive_info *hive = NULL;
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
int i, r = 0;
|
||||
bool need_emergency_restart = false;
|
||||
bool audio_suspended = false;
|
||||
int tmp_vram_lost_counter;
|
||||
struct amdgpu_reset_context reset_context;
|
||||
|
||||
memset(&reset_context, 0, sizeof(reset_context));
|
||||
|
||||
/*
|
||||
* Special case: RAS triggered and full reset isn't supported
|
||||
@ -4677,6 +4755,12 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
mutex_lock(&hive->hive_lock);
|
||||
}
|
||||
|
||||
reset_context.method = AMD_RESET_METHOD_NONE;
|
||||
reset_context.reset_req_dev = adev;
|
||||
reset_context.job = job;
|
||||
reset_context.hive = hive;
|
||||
clear_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
|
||||
|
||||
/*
|
||||
* lock the device before we try to operate the linked list
|
||||
* if didn't get the device lock, don't touch the linked list since
|
||||
@ -4777,9 +4861,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
|
||||
retry: /* Rest of adevs pre asic reset from XGMI hive. */
|
||||
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
|
||||
r = amdgpu_device_pre_asic_reset(tmp_adev,
|
||||
(tmp_adev == adev) ? job : NULL,
|
||||
&need_full_reset);
|
||||
r = amdgpu_device_pre_asic_reset(tmp_adev, &reset_context);
|
||||
/*TODO Should we stop ?*/
|
||||
if (r) {
|
||||
dev_err(tmp_adev->dev, "GPU pre asic reset failed with err, %d for drm dev, %s ",
|
||||
@ -4788,6 +4870,7 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */
|
||||
}
|
||||
}
|
||||
|
||||
tmp_vram_lost_counter = atomic_read(&((adev)->vram_lost_counter));
|
||||
/* Actual ASIC resets if needed.*/
|
||||
/* TODO Implement XGMI hive reset logic for SRIOV */
|
||||
if (amdgpu_sriov_vf(adev)) {
|
||||
@ -4795,7 +4878,7 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */
|
||||
if (r)
|
||||
adev->asic_reset_res = r;
|
||||
} else {
|
||||
r = amdgpu_do_asic_reset(hive, device_list_handle, &need_full_reset, false);
|
||||
r = amdgpu_do_asic_reset(device_list_handle, &reset_context);
|
||||
if (r && r == -EAGAIN)
|
||||
goto retry;
|
||||
}
|
||||
@ -4805,6 +4888,18 @@ skip_hw_reset:
|
||||
/* Post ASIC reset for all devs .*/
|
||||
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
|
||||
|
||||
/*
|
||||
* Sometimes a later bad compute job can block a good gfx job as gfx
|
||||
* and compute ring share internal GC HW mutually. We add an additional
|
||||
* guilty jobs recheck step to find the real guilty job, it synchronously
|
||||
* submits and pends for the first job being signaled. If it gets timeout,
|
||||
* we identify it as a real guilty job.
|
||||
*/
|
||||
if (amdgpu_gpu_recovery == 2 &&
|
||||
!(tmp_vram_lost_counter < atomic_read(&adev->vram_lost_counter)))
|
||||
amdgpu_device_recheck_guilty_jobs(
|
||||
tmp_adev, device_list_handle, &reset_context);
|
||||
|
||||
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
|
||||
struct amdgpu_ring *ring = tmp_adev->rings[i];
|
||||
|
||||
@ -5148,12 +5243,14 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
int r, i;
|
||||
bool need_full_reset = true;
|
||||
struct amdgpu_reset_context reset_context;
|
||||
u32 memsize;
|
||||
struct list_head device_list;
|
||||
|
||||
DRM_INFO("PCI error: slot reset callback!!\n");
|
||||
|
||||
memset(&reset_context, 0, sizeof(reset_context));
|
||||
|
||||
INIT_LIST_HEAD(&device_list);
|
||||
list_add_tail(&adev->reset_list, &device_list);
|
||||
|
||||
@ -5176,13 +5273,18 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
reset_context.method = AMD_RESET_METHOD_NONE;
|
||||
reset_context.reset_req_dev = adev;
|
||||
set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
|
||||
set_bit(AMDGPU_SKIP_HW_RESET, &reset_context.flags);
|
||||
|
||||
adev->in_pci_err_recovery = true;
|
||||
r = amdgpu_device_pre_asic_reset(adev, NULL, &need_full_reset);
|
||||
r = amdgpu_device_pre_asic_reset(adev, &reset_context);
|
||||
adev->in_pci_err_recovery = false;
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
r = amdgpu_do_asic_reset(NULL, &device_list, &need_full_reset, true);
|
||||
r = amdgpu_do_asic_reset(&device_list, &reset_context);
|
||||
|
||||
out:
|
||||
if (!r) {
|
||||
|
@ -1354,3 +1354,92 @@ bool amdgpu_crtc_get_scanout_position(struct drm_crtc *crtc,
|
||||
return amdgpu_display_get_crtc_scanoutpos(dev, pipe, 0, vpos, hpos,
|
||||
stime, etime, mode);
|
||||
}
|
||||
|
||||
int amdgpu_display_suspend_helper(struct amdgpu_device *adev)
|
||||
{
|
||||
struct drm_device *dev = adev_to_drm(adev);
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter iter;
|
||||
int r;
|
||||
|
||||
/* turn off display hw */
|
||||
drm_modeset_lock_all(dev);
|
||||
drm_connector_list_iter_begin(dev, &iter);
|
||||
drm_for_each_connector_iter(connector, &iter)
|
||||
drm_helper_connector_dpms(connector,
|
||||
DRM_MODE_DPMS_OFF);
|
||||
drm_connector_list_iter_end(&iter);
|
||||
drm_modeset_unlock_all(dev);
|
||||
/* 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 drm_framebuffer *fb = crtc->primary->fb;
|
||||
struct amdgpu_bo *robj;
|
||||
|
||||
if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
|
||||
struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
|
||||
r = amdgpu_bo_reserve(aobj, true);
|
||||
if (r == 0) {
|
||||
amdgpu_bo_unpin(aobj);
|
||||
amdgpu_bo_unreserve(aobj);
|
||||
}
|
||||
}
|
||||
|
||||
if (fb == NULL || fb->obj[0] == NULL) {
|
||||
continue;
|
||||
}
|
||||
robj = gem_to_amdgpu_bo(fb->obj[0]);
|
||||
/* don't unpin kernel fb objects */
|
||||
if (!amdgpu_fbdev_robj_is_fb(adev, robj)) {
|
||||
r = amdgpu_bo_reserve(robj, true);
|
||||
if (r == 0) {
|
||||
amdgpu_bo_unpin(robj);
|
||||
amdgpu_bo_unreserve(robj);
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_display_resume_helper(struct amdgpu_device *adev)
|
||||
{
|
||||
struct drm_device *dev = adev_to_drm(adev);
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter iter;
|
||||
struct drm_crtc *crtc;
|
||||
int 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 && !adev->enable_virtual_display) {
|
||||
struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
|
||||
r = amdgpu_bo_reserve(aobj, true);
|
||||
if (r == 0) {
|
||||
r = amdgpu_bo_pin(aobj, AMDGPU_GEM_DOMAIN_VRAM);
|
||||
if (r != 0)
|
||||
dev_err(adev->dev, "Failed to pin cursor BO (%d)\n", r);
|
||||
amdgpu_crtc->cursor_addr = amdgpu_bo_gpu_offset(aobj);
|
||||
amdgpu_bo_unreserve(aobj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drm_helper_resume_force_mode(dev);
|
||||
|
||||
/* turn on display hw */
|
||||
drm_modeset_lock_all(dev);
|
||||
|
||||
drm_connector_list_iter_begin(dev, &iter);
|
||||
drm_for_each_connector_iter(connector, &iter)
|
||||
drm_helper_connector_dpms(connector,
|
||||
DRM_MODE_DPMS_ON);
|
||||
drm_connector_list_iter_end(&iter);
|
||||
|
||||
drm_modeset_unlock_all(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -47,4 +47,7 @@ amdgpu_display_user_framebuffer_create(struct drm_device *dev,
|
||||
const struct drm_format_info *
|
||||
amdgpu_lookup_format_info(u32 format, uint64_t modifier);
|
||||
|
||||
int amdgpu_display_suspend_helper(struct amdgpu_device *adev);
|
||||
int amdgpu_display_resume_helper(struct amdgpu_device *adev);
|
||||
|
||||
#endif
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <linux/vga_switcheroo.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <linux/mmu_notifier.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_irq.h"
|
||||
@ -46,6 +47,7 @@
|
||||
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_xgmi.h"
|
||||
#include "amdgpu_reset.h"
|
||||
|
||||
/*
|
||||
* KMS wrapper.
|
||||
@ -515,7 +517,7 @@ module_param_named(compute_multipipe, amdgpu_compute_multipipe, int, 0444);
|
||||
* DOC: gpu_recovery (int)
|
||||
* Set to enable GPU recovery mechanism (1 = enable, 0 = disable). The default is -1 (auto, disabled except SRIOV).
|
||||
*/
|
||||
MODULE_PARM_DESC(gpu_recovery, "Enable GPU recovery mechanism, (1 = enable, 0 = disable, -1 = auto)");
|
||||
MODULE_PARM_DESC(gpu_recovery, "Enable GPU recovery mechanism, (2 = advanced tdr mode, 1 = enable, 0 = disable, -1 = auto)");
|
||||
module_param_named(gpu_recovery, amdgpu_gpu_recovery, int, 0444);
|
||||
|
||||
/**
|
||||
@ -1161,6 +1163,7 @@ static const struct pci_device_id pciidlist[] = {
|
||||
{0x1002, 0x73A3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
|
||||
{0x1002, 0x73AB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
|
||||
{0x1002, 0x73AE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
|
||||
{0x1002, 0x73AF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
|
||||
{0x1002, 0x73BF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
|
||||
|
||||
/* Van Gogh */
|
||||
@ -1333,9 +1336,7 @@ amdgpu_pci_shutdown(struct pci_dev *pdev)
|
||||
*/
|
||||
if (!amdgpu_passthrough(adev))
|
||||
adev->mp1_state = PP_MP1_STATE_UNLOAD;
|
||||
adev->in_poweroff_reboot_com = true;
|
||||
amdgpu_device_ip_suspend(adev);
|
||||
adev->in_poweroff_reboot_com = false;
|
||||
adev->mp1_state = PP_MP1_STATE_NONE;
|
||||
}
|
||||
|
||||
@ -1349,7 +1350,9 @@ static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work)
|
||||
struct list_head device_list;
|
||||
struct amdgpu_device *adev;
|
||||
int i, r;
|
||||
bool need_full_reset = true;
|
||||
struct amdgpu_reset_context reset_context;
|
||||
|
||||
memset(&reset_context, 0, sizeof(reset_context));
|
||||
|
||||
mutex_lock(&mgpu_info.mutex);
|
||||
if (mgpu_info.pending_reset == true) {
|
||||
@ -1359,9 +1362,14 @@ static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work)
|
||||
mgpu_info.pending_reset = true;
|
||||
mutex_unlock(&mgpu_info.mutex);
|
||||
|
||||
/* Use a common context, just need to make sure full reset is done */
|
||||
reset_context.method = AMD_RESET_METHOD_NONE;
|
||||
set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
|
||||
|
||||
for (i = 0; i < mgpu_info.num_dgpu; i++) {
|
||||
adev = mgpu_info.gpu_ins[i].adev;
|
||||
r = amdgpu_device_pre_asic_reset(adev, NULL, &need_full_reset);
|
||||
reset_context.reset_req_dev = adev;
|
||||
r = amdgpu_device_pre_asic_reset(adev, &reset_context);
|
||||
if (r) {
|
||||
dev_err(adev->dev, "GPU pre asic reset failed with err, %d for drm dev, %s ",
|
||||
r, adev_to_drm(adev)->unique);
|
||||
@ -1388,7 +1396,10 @@ static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work)
|
||||
list_for_each_entry(adev, &device_list, reset_list)
|
||||
amdgpu_unregister_gpu_instance(adev);
|
||||
|
||||
r = amdgpu_do_asic_reset(NULL, &device_list, &need_full_reset, true);
|
||||
/* Use a common context, just need to make sure full reset is done */
|
||||
set_bit(AMDGPU_SKIP_HW_RESET, &reset_context.flags);
|
||||
r = amdgpu_do_asic_reset(&device_list, &reset_context);
|
||||
|
||||
if (r) {
|
||||
DRM_ERROR("reinit gpus failure");
|
||||
return;
|
||||
@ -1402,18 +1413,50 @@ static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work)
|
||||
return;
|
||||
}
|
||||
|
||||
static int amdgpu_pmops_suspend(struct device *dev)
|
||||
static int amdgpu_pmops_prepare(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
|
||||
return amdgpu_device_suspend(drm_dev, true);
|
||||
/* Return a positive number here so
|
||||
* DPM_FLAG_SMART_SUSPEND works properly
|
||||
*/
|
||||
if (amdgpu_device_supports_boco(drm_dev))
|
||||
return pm_runtime_suspended(dev) &&
|
||||
pm_suspend_via_firmware();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amdgpu_pmops_complete(struct device *dev)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
static int amdgpu_pmops_suspend(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(drm_dev);
|
||||
int r;
|
||||
|
||||
if (amdgpu_acpi_is_s0ix_supported(adev))
|
||||
adev->in_s0ix = true;
|
||||
adev->in_s3 = true;
|
||||
r = amdgpu_device_suspend(drm_dev, true);
|
||||
adev->in_s3 = false;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int amdgpu_pmops_resume(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(drm_dev);
|
||||
int r;
|
||||
|
||||
return amdgpu_device_resume(drm_dev, true);
|
||||
r = amdgpu_device_resume(drm_dev, true);
|
||||
if (amdgpu_acpi_is_s0ix_supported(adev))
|
||||
adev->in_s0ix = false;
|
||||
return r;
|
||||
}
|
||||
|
||||
static int amdgpu_pmops_freeze(struct device *dev)
|
||||
@ -1422,9 +1465,9 @@ static int amdgpu_pmops_freeze(struct device *dev)
|
||||
struct amdgpu_device *adev = drm_to_adev(drm_dev);
|
||||
int r;
|
||||
|
||||
adev->in_hibernate = true;
|
||||
adev->in_s4 = true;
|
||||
r = amdgpu_device_suspend(drm_dev, true);
|
||||
adev->in_hibernate = false;
|
||||
adev->in_s4 = false;
|
||||
if (r)
|
||||
return r;
|
||||
return amdgpu_asic_reset(adev);
|
||||
@ -1440,13 +1483,8 @@ static int amdgpu_pmops_thaw(struct device *dev)
|
||||
static int amdgpu_pmops_poweroff(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(drm_dev);
|
||||
int r;
|
||||
|
||||
adev->in_poweroff_reboot_com = true;
|
||||
r = amdgpu_device_suspend(drm_dev, true);
|
||||
adev->in_poweroff_reboot_com = false;
|
||||
return r;
|
||||
return amdgpu_device_suspend(drm_dev, true);
|
||||
}
|
||||
|
||||
static int amdgpu_pmops_restore(struct device *dev)
|
||||
@ -1479,7 +1517,7 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
|
||||
}
|
||||
|
||||
adev->in_runpm = true;
|
||||
if (amdgpu_device_supports_atpx(drm_dev))
|
||||
if (amdgpu_device_supports_px(drm_dev))
|
||||
drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||
|
||||
ret = amdgpu_device_suspend(drm_dev, false);
|
||||
@ -1488,16 +1526,14 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (amdgpu_device_supports_atpx(drm_dev)) {
|
||||
if (amdgpu_device_supports_px(drm_dev)) {
|
||||
/* Only need to handle PCI state in the driver for ATPX
|
||||
* PCI core handles it for _PR3.
|
||||
*/
|
||||
if (!amdgpu_is_atpx_hybrid()) {
|
||||
amdgpu_device_cache_pci_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
pci_ignore_hotplug(pdev);
|
||||
pci_set_power_state(pdev, PCI_D3cold);
|
||||
}
|
||||
amdgpu_device_cache_pci_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
pci_ignore_hotplug(pdev);
|
||||
pci_set_power_state(pdev, PCI_D3cold);
|
||||
drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF;
|
||||
} else if (amdgpu_device_supports_baco(drm_dev)) {
|
||||
amdgpu_device_baco_enter(drm_dev);
|
||||
@ -1516,19 +1552,17 @@ static int amdgpu_pmops_runtime_resume(struct device *dev)
|
||||
if (!adev->runpm)
|
||||
return -EINVAL;
|
||||
|
||||
if (amdgpu_device_supports_atpx(drm_dev)) {
|
||||
if (amdgpu_device_supports_px(drm_dev)) {
|
||||
drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||
|
||||
/* Only need to handle PCI state in the driver for ATPX
|
||||
* PCI core handles it for _PR3.
|
||||
*/
|
||||
if (!amdgpu_is_atpx_hybrid()) {
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
amdgpu_device_load_pci_state(pdev);
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
amdgpu_device_load_pci_state(pdev);
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
pci_set_master(pdev);
|
||||
} else if (amdgpu_device_supports_boco(drm_dev)) {
|
||||
/* Only need to handle PCI state in the driver for ATPX
|
||||
@ -1539,7 +1573,7 @@ static int amdgpu_pmops_runtime_resume(struct device *dev)
|
||||
amdgpu_device_baco_exit(drm_dev);
|
||||
}
|
||||
ret = amdgpu_device_resume(drm_dev, false);
|
||||
if (amdgpu_device_supports_atpx(drm_dev))
|
||||
if (amdgpu_device_supports_px(drm_dev))
|
||||
drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;
|
||||
adev->in_runpm = false;
|
||||
return 0;
|
||||
@ -1620,6 +1654,8 @@ out:
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops amdgpu_pm_ops = {
|
||||
.prepare = amdgpu_pmops_prepare,
|
||||
.complete = amdgpu_pmops_complete,
|
||||
.suspend = amdgpu_pmops_suspend,
|
||||
.resume = amdgpu_pmops_resume,
|
||||
.freeze = amdgpu_pmops_freeze,
|
||||
|
@ -439,7 +439,8 @@ int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
|
||||
* Helper function for amdgpu_fence_driver_init().
|
||||
*/
|
||||
int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
|
||||
unsigned num_hw_submission)
|
||||
unsigned num_hw_submission,
|
||||
atomic_t *sched_score)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
long timeout;
|
||||
@ -467,30 +468,31 @@ int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
|
||||
return -ENOMEM;
|
||||
|
||||
/* No need to setup the GPU scheduler for rings that don't need it */
|
||||
if (!ring->no_scheduler) {
|
||||
switch (ring->funcs->type) {
|
||||
case AMDGPU_RING_TYPE_GFX:
|
||||
timeout = adev->gfx_timeout;
|
||||
break;
|
||||
case AMDGPU_RING_TYPE_COMPUTE:
|
||||
timeout = adev->compute_timeout;
|
||||
break;
|
||||
case AMDGPU_RING_TYPE_SDMA:
|
||||
timeout = adev->sdma_timeout;
|
||||
break;
|
||||
default:
|
||||
timeout = adev->video_timeout;
|
||||
break;
|
||||
}
|
||||
if (ring->no_scheduler)
|
||||
return 0;
|
||||
|
||||
r = drm_sched_init(&ring->sched, &amdgpu_sched_ops,
|
||||
num_hw_submission, amdgpu_job_hang_limit,
|
||||
timeout, NULL, ring->name);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to create scheduler on ring %s.\n",
|
||||
ring->name);
|
||||
return r;
|
||||
}
|
||||
switch (ring->funcs->type) {
|
||||
case AMDGPU_RING_TYPE_GFX:
|
||||
timeout = adev->gfx_timeout;
|
||||
break;
|
||||
case AMDGPU_RING_TYPE_COMPUTE:
|
||||
timeout = adev->compute_timeout;
|
||||
break;
|
||||
case AMDGPU_RING_TYPE_SDMA:
|
||||
timeout = adev->sdma_timeout;
|
||||
break;
|
||||
default:
|
||||
timeout = adev->video_timeout;
|
||||
break;
|
||||
}
|
||||
|
||||
r = drm_sched_init(&ring->sched, &amdgpu_sched_ops,
|
||||
num_hw_submission, amdgpu_job_hang_limit,
|
||||
timeout, sched_score, ring->name);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to create scheduler on ring %s.\n",
|
||||
ring->name);
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -126,6 +126,8 @@ int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev)
|
||||
AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
|
||||
bp.type = ttm_bo_type_kernel;
|
||||
bp.resv = NULL;
|
||||
bp.bo_ptr_size = sizeof(struct amdgpu_bo);
|
||||
|
||||
r = amdgpu_bo_create(adev, &bp, &adev->gart.bo);
|
||||
if (r) {
|
||||
return r;
|
||||
|
@ -58,6 +58,7 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
|
||||
struct drm_gem_object **obj)
|
||||
{
|
||||
struct amdgpu_bo *bo;
|
||||
struct amdgpu_bo_user *ubo;
|
||||
struct amdgpu_bo_param bp;
|
||||
int r;
|
||||
|
||||
@ -71,10 +72,13 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
|
||||
bp.preferred_domain = initial_domain;
|
||||
bp.flags = flags;
|
||||
bp.domain = initial_domain;
|
||||
r = amdgpu_bo_create(adev, &bp, &bo);
|
||||
bp.bo_ptr_size = sizeof(struct amdgpu_bo);
|
||||
|
||||
r = amdgpu_bo_create_user(adev, &bp, &ubo);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
bo = &ubo->bo;
|
||||
*obj = &bo->tbo.base;
|
||||
(*obj)->funcs = &amdgpu_gem_object_funcs;
|
||||
|
||||
|
@ -310,9 +310,8 @@ int amdgpu_gfx_kiq_init_ring(struct amdgpu_device *adev,
|
||||
ring->eop_gpu_addr = kiq->eop_gpu_addr;
|
||||
ring->no_scheduler = true;
|
||||
sprintf(ring->name, "kiq_%d.%d.%d", ring->me, ring->pipe, ring->queue);
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
irq, AMDGPU_CP_KIQ_IRQ_DRIVER0,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
r = amdgpu_ring_init(adev, ring, 1024, irq, AMDGPU_CP_KIQ_IRQ_DRIVER0,
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
dev_warn(adev->dev, "(%d) failed to init kiq ring\n", r);
|
||||
|
||||
@ -463,20 +462,25 @@ int amdgpu_gfx_disable_kcq(struct amdgpu_device *adev)
|
||||
{
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq;
|
||||
struct amdgpu_ring *kiq_ring = &kiq->ring;
|
||||
int i;
|
||||
int i, r;
|
||||
|
||||
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&adev->gfx.kiq.ring_lock);
|
||||
if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size *
|
||||
adev->gfx.num_compute_rings))
|
||||
adev->gfx.num_compute_rings)) {
|
||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < adev->gfx.num_compute_rings; i++)
|
||||
kiq->pmf->kiq_unmap_queues(kiq_ring, &adev->gfx.compute_ring[i],
|
||||
RESET_QUEUES, 0, 0);
|
||||
r = amdgpu_ring_test_helper(kiq_ring);
|
||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||
|
||||
return amdgpu_ring_test_helper(kiq_ring);
|
||||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_queue_mask_bit_to_set_resource_bit(struct amdgpu_device *adev,
|
||||
@ -519,12 +523,13 @@ int amdgpu_gfx_enable_kcq(struct amdgpu_device *adev)
|
||||
|
||||
DRM_INFO("kiq ring mec %d pipe %d q %d\n", kiq_ring->me, kiq_ring->pipe,
|
||||
kiq_ring->queue);
|
||||
|
||||
spin_lock(&adev->gfx.kiq.ring_lock);
|
||||
r = amdgpu_ring_alloc(kiq_ring, kiq->pmf->map_queues_size *
|
||||
adev->gfx.num_compute_rings +
|
||||
kiq->pmf->set_resources_size);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to lock KIQ (%d).\n", r);
|
||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -533,6 +538,7 @@ int amdgpu_gfx_enable_kcq(struct amdgpu_device *adev)
|
||||
kiq->pmf->kiq_map_queues(kiq_ring, &adev->gfx.compute_ring[i]);
|
||||
|
||||
r = amdgpu_ring_test_helper(kiq_ring);
|
||||
spin_unlock(&adev->gfx.kiq.ring_lock);
|
||||
if (r)
|
||||
DRM_ERROR("KCQ enable failed\n");
|
||||
|
||||
@ -671,8 +677,9 @@ int amdgpu_gfx_process_ras_data_cb(struct amdgpu_device *adev,
|
||||
*/
|
||||
if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX)) {
|
||||
kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
|
||||
if (adev->gfx.funcs->query_ras_error_count)
|
||||
adev->gfx.funcs->query_ras_error_count(adev, err_data);
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->query_ras_error_count)
|
||||
adev->gfx.ras_funcs->query_ras_error_count(adev, err_data);
|
||||
amdgpu_ras_reset_gpu(adev);
|
||||
}
|
||||
return AMDGPU_RAS_SUCCESS;
|
||||
@ -705,7 +712,7 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg)
|
||||
struct amdgpu_kiq *kiq = &adev->gfx.kiq;
|
||||
struct amdgpu_ring *ring = &kiq->ring;
|
||||
|
||||
if (adev->in_pci_err_recovery)
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
return 0;
|
||||
|
||||
BUG_ON(!ring->funcs->emit_rreg);
|
||||
@ -772,7 +779,7 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v)
|
||||
|
||||
BUG_ON(!ring->funcs->emit_wreg);
|
||||
|
||||
if (adev->in_pci_err_recovery)
|
||||
if (amdgpu_device_skip_hw_access(adev))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&kiq->ring_lock, flags);
|
||||
@ -836,14 +843,10 @@ int amdgpu_gfx_get_num_kcq(struct amdgpu_device *adev)
|
||||
|
||||
void amdgpu_gfx_state_change_set(struct amdgpu_device *adev, enum gfx_change_state state)
|
||||
{
|
||||
if (is_support_sw_smu(adev)) {
|
||||
smu_gfx_state_change_set(&adev->smu, state);
|
||||
} else {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
if (adev->powerplay.pp_funcs &&
|
||||
adev->powerplay.pp_funcs->gfx_state_change_set)
|
||||
((adev)->powerplay.pp_funcs->gfx_state_change_set(
|
||||
(adev)->powerplay.pp_handle, state));
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
if (adev->powerplay.pp_funcs &&
|
||||
adev->powerplay.pp_funcs->gfx_state_change_set)
|
||||
((adev)->powerplay.pp_funcs->gfx_state_change_set(
|
||||
(adev)->powerplay.pp_handle, state));
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
|
@ -205,6 +205,19 @@ struct amdgpu_cu_info {
|
||||
uint32_t bitmap[4][4];
|
||||
};
|
||||
|
||||
struct amdgpu_gfx_ras_funcs {
|
||||
int (*ras_late_init)(struct amdgpu_device *adev);
|
||||
void (*ras_fini)(struct amdgpu_device *adev);
|
||||
int (*ras_error_inject)(struct amdgpu_device *adev,
|
||||
void *inject_if);
|
||||
int (*query_ras_error_count)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
void (*reset_ras_error_count)(struct amdgpu_device *adev);
|
||||
void (*query_ras_error_status)(struct amdgpu_device *adev);
|
||||
void (*reset_ras_error_status)(struct amdgpu_device *adev);
|
||||
void (*enable_watchdog_timer)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
struct amdgpu_gfx_funcs {
|
||||
/* get the gpu clock counter */
|
||||
uint64_t (*get_gpu_clock_counter)(struct amdgpu_device *adev);
|
||||
@ -220,14 +233,8 @@ struct amdgpu_gfx_funcs {
|
||||
uint32_t *dst);
|
||||
void (*select_me_pipe_q)(struct amdgpu_device *adev, u32 me, u32 pipe,
|
||||
u32 queue, u32 vmid);
|
||||
int (*ras_error_inject)(struct amdgpu_device *adev, void *inject_if);
|
||||
int (*query_ras_error_count) (struct amdgpu_device *adev, void *ras_error_status);
|
||||
void (*reset_ras_error_count) (struct amdgpu_device *adev);
|
||||
void (*init_spm_golden)(struct amdgpu_device *adev);
|
||||
void (*query_ras_error_status) (struct amdgpu_device *adev);
|
||||
void (*reset_ras_error_status) (struct amdgpu_device *adev);
|
||||
void (*update_perfmon_mgcg)(struct amdgpu_device *adev, bool enable);
|
||||
void (*enable_watchdog_timer)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
struct sq_work {
|
||||
@ -330,7 +337,8 @@ struct amdgpu_gfx {
|
||||
DECLARE_BITMAP (pipe_reserve_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
|
||||
|
||||
/*ras */
|
||||
struct ras_common_if *ras_if;
|
||||
struct ras_common_if *ras_if;
|
||||
const struct amdgpu_gfx_ras_funcs *ras_funcs;
|
||||
};
|
||||
|
||||
#define amdgpu_gfx_get_gpu_clock_counter(adev) (adev)->gfx.funcs->get_gpu_clock_counter((adev))
|
||||
|
@ -55,6 +55,8 @@ int amdgpu_gmc_pdb0_alloc(struct amdgpu_device *adev)
|
||||
AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
|
||||
bp.type = ttm_bo_type_kernel;
|
||||
bp.resv = NULL;
|
||||
bp.bo_ptr_size = sizeof(struct amdgpu_bo);
|
||||
|
||||
r = amdgpu_bo_create(adev, &bp, &adev->gmc.pdb0_bo);
|
||||
if (r)
|
||||
return r;
|
||||
@ -389,26 +391,46 @@ int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (adev->umc.funcs && adev->umc.funcs->ras_late_init) {
|
||||
r = adev->umc.funcs->ras_late_init(adev);
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->ras_late_init) {
|
||||
r = adev->umc.ras_funcs->ras_late_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (adev->mmhub.funcs && adev->mmhub.funcs->ras_late_init) {
|
||||
r = adev->mmhub.funcs->ras_late_init(adev);
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->ras_late_init) {
|
||||
r = adev->mmhub.ras_funcs->ras_late_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return amdgpu_xgmi_ras_late_init(adev);
|
||||
if (!adev->gmc.xgmi.connected_to_cpu)
|
||||
adev->gmc.xgmi.ras_funcs = &xgmi_ras_funcs;
|
||||
|
||||
if (adev->gmc.xgmi.ras_funcs &&
|
||||
adev->gmc.xgmi.ras_funcs->ras_late_init) {
|
||||
r = adev->gmc.xgmi.ras_funcs->ras_late_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_gmc_ras_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
amdgpu_umc_ras_fini(adev);
|
||||
amdgpu_mmhub_ras_fini(adev);
|
||||
amdgpu_xgmi_ras_fini(adev);
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->ras_fini)
|
||||
adev->umc.ras_funcs->ras_fini(adev);
|
||||
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->ras_fini)
|
||||
amdgpu_mmhub_ras_fini(adev);
|
||||
|
||||
if (adev->gmc.xgmi.ras_funcs &&
|
||||
adev->gmc.xgmi.ras_funcs->ras_fini)
|
||||
adev->gmc.xgmi.ras_funcs->ras_fini(adev);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -514,6 +536,7 @@ void amdgpu_gmc_noretry_set(struct amdgpu_device *adev)
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA10:
|
||||
case CHIP_VEGA20:
|
||||
case CHIP_ARCTURUS:
|
||||
case CHIP_ALDEBARAN:
|
||||
/*
|
||||
* noretry = 0 will cause kfd page fault tests fail
|
||||
|
@ -135,6 +135,14 @@ struct amdgpu_gmc_funcs {
|
||||
unsigned int (*get_vbios_fb_size)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
struct amdgpu_xgmi_ras_funcs {
|
||||
int (*ras_late_init)(struct amdgpu_device *adev);
|
||||
void (*ras_fini)(struct amdgpu_device *adev);
|
||||
int (*query_ras_error_count)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
void (*reset_ras_error_count)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
struct amdgpu_xgmi {
|
||||
/* from psp */
|
||||
u64 node_id;
|
||||
@ -151,6 +159,7 @@ struct amdgpu_xgmi {
|
||||
struct ras_common_if *ras_if;
|
||||
bool connected_to_cpu;
|
||||
bool pending_reset;
|
||||
const struct amdgpu_xgmi_ras_funcs *ras_funcs;
|
||||
};
|
||||
|
||||
struct amdgpu_gmc {
|
||||
|
@ -49,8 +49,7 @@ static ssize_t amdgpu_mem_info_gtt_total_show(struct device *dev,
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%llu\n",
|
||||
man->size * PAGE_SIZE);
|
||||
return sysfs_emit(buf, "%llu\n", man->size * PAGE_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,8 +67,7 @@ static ssize_t amdgpu_mem_info_gtt_used_show(struct device *dev,
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%llu\n",
|
||||
amdgpu_gtt_mgr_usage(man));
|
||||
return sysfs_emit(buf, "%llu\n", amdgpu_gtt_mgr_usage(man));
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(mem_info_gtt_total, S_IRUGO,
|
||||
|
@ -199,13 +199,13 @@ irqreturn_t amdgpu_irq_handler(int irq, void *arg)
|
||||
* ack the interrupt if it is there
|
||||
*/
|
||||
if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__PCIE_BIF)) {
|
||||
if (adev->nbio.funcs &&
|
||||
adev->nbio.funcs->handle_ras_controller_intr_no_bifring)
|
||||
adev->nbio.funcs->handle_ras_controller_intr_no_bifring(adev);
|
||||
if (adev->nbio.ras_funcs &&
|
||||
adev->nbio.ras_funcs->handle_ras_controller_intr_no_bifring)
|
||||
adev->nbio.ras_funcs->handle_ras_controller_intr_no_bifring(adev);
|
||||
|
||||
if (adev->nbio.funcs &&
|
||||
adev->nbio.funcs->handle_ras_err_event_athub_intr_no_bifring)
|
||||
adev->nbio.funcs->handle_ras_err_event_athub_intr_no_bifring(adev);
|
||||
if (adev->nbio.ras_funcs &&
|
||||
adev->nbio.ras_funcs->handle_ras_err_event_athub_intr_no_bifring)
|
||||
adev->nbio.ras_funcs->handle_ras_err_event_athub_intr_no_bifring(adev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -382,11 +382,6 @@ void amdgpu_irq_fini(struct amdgpu_device *adev)
|
||||
|
||||
kfree(src->enabled_types);
|
||||
src->enabled_types = NULL;
|
||||
if (src->data) {
|
||||
kfree(src->data);
|
||||
kfree(src);
|
||||
adev->irq.client[i].sources[j] = NULL;
|
||||
}
|
||||
}
|
||||
kfree(adev->irq.client[i].sources);
|
||||
adev->irq.client[i].sources = NULL;
|
||||
|
@ -62,7 +62,6 @@ struct amdgpu_irq_src {
|
||||
unsigned num_types;
|
||||
atomic_t *enabled_types;
|
||||
const struct amdgpu_irq_src_funcs *funcs;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct amdgpu_irq_client {
|
||||
|
@ -159,7 +159,7 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (amdgpu_device_supports_atpx(dev) &&
|
||||
if (amdgpu_device_supports_px(dev) &&
|
||||
(amdgpu_runtime_pm != 0)) { /* enable runpm by default for atpx */
|
||||
adev->runpm = true;
|
||||
dev_info(adev->dev, "Using ATPX for runtime pm\n");
|
||||
@ -200,9 +200,13 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags)
|
||||
|
||||
if (adev->runpm) {
|
||||
/* only need to skip on ATPX */
|
||||
if (amdgpu_device_supports_atpx(dev) &&
|
||||
!amdgpu_is_atpx_hybrid())
|
||||
if (amdgpu_device_supports_px(dev))
|
||||
dev_pm_set_driver_flags(dev->dev, DPM_FLAG_NO_DIRECT_COMPLETE);
|
||||
/* we want direct complete for BOCO */
|
||||
if (amdgpu_device_supports_boco(dev))
|
||||
dev_pm_set_driver_flags(dev->dev, DPM_FLAG_SMART_PREPARE |
|
||||
DPM_FLAG_SMART_SUSPEND |
|
||||
DPM_FLAG_MAY_SKIP_RESUME);
|
||||
pm_runtime_use_autosuspend(dev->dev);
|
||||
pm_runtime_set_autosuspend_delay(dev->dev, 5000);
|
||||
pm_runtime_allow(dev->dev);
|
||||
@ -785,9 +789,9 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
|
||||
dev_info->high_va_offset = AMDGPU_GMC_HOLE_END;
|
||||
dev_info->high_va_max = AMDGPU_GMC_HOLE_END | vm_size;
|
||||
}
|
||||
dev_info->virtual_address_alignment = max((int)PAGE_SIZE, AMDGPU_GPU_PAGE_SIZE);
|
||||
dev_info->virtual_address_alignment = max_t(u32, PAGE_SIZE, AMDGPU_GPU_PAGE_SIZE);
|
||||
dev_info->pte_fragment_size = (1 << adev->vm_manager.fragment_size) * AMDGPU_GPU_PAGE_SIZE;
|
||||
dev_info->gart_page_size = AMDGPU_GPU_PAGE_SIZE;
|
||||
dev_info->gart_page_size = max_t(u32, PAGE_SIZE, AMDGPU_GPU_PAGE_SIZE);
|
||||
dev_info->cu_active_number = adev->gfx.cu_info.number;
|
||||
dev_info->cu_ao_mask = adev->gfx.cu_info.ao_cu_mask;
|
||||
dev_info->ce_ram_size = adev->gfx.ce_ram_size;
|
||||
|
@ -21,12 +21,16 @@
|
||||
#ifndef __AMDGPU_MMHUB_H__
|
||||
#define __AMDGPU_MMHUB_H__
|
||||
|
||||
struct amdgpu_mmhub_funcs {
|
||||
void (*ras_init)(struct amdgpu_device *adev);
|
||||
struct amdgpu_mmhub_ras_funcs {
|
||||
int (*ras_late_init)(struct amdgpu_device *adev);
|
||||
void (*ras_fini)(struct amdgpu_device *adev);
|
||||
void (*query_ras_error_count)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
void *ras_error_status);
|
||||
void (*query_ras_error_status)(struct amdgpu_device *adev);
|
||||
void (*reset_ras_error_count)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
struct amdgpu_mmhub_funcs {
|
||||
u64 (*get_fb_location)(struct amdgpu_device *adev);
|
||||
void (*init)(struct amdgpu_device *adev);
|
||||
int (*gart_enable)(struct amdgpu_device *adev);
|
||||
@ -40,12 +44,12 @@ struct amdgpu_mmhub_funcs {
|
||||
uint64_t page_table_base);
|
||||
void (*update_power_gating)(struct amdgpu_device *adev,
|
||||
bool enable);
|
||||
void (*query_ras_error_status)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
struct amdgpu_mmhub {
|
||||
struct ras_common_if *ras_if;
|
||||
const struct amdgpu_mmhub_funcs *funcs;
|
||||
const struct amdgpu_mmhub_ras_funcs *ras_funcs;
|
||||
};
|
||||
|
||||
int amdgpu_mmhub_ras_late_init(struct amdgpu_device *adev);
|
||||
|
@ -47,6 +47,17 @@ struct nbio_hdp_flush_reg {
|
||||
u32 ref_and_mask_sdma7;
|
||||
};
|
||||
|
||||
struct amdgpu_nbio_ras_funcs {
|
||||
void (*handle_ras_controller_intr_no_bifring)(struct amdgpu_device *adev);
|
||||
void (*handle_ras_err_event_athub_intr_no_bifring)(struct amdgpu_device *adev);
|
||||
int (*init_ras_controller_interrupt)(struct amdgpu_device *adev);
|
||||
int (*init_ras_err_event_athub_interrupt)(struct amdgpu_device *adev);
|
||||
void (*query_ras_error_count)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
int (*ras_late_init)(struct amdgpu_device *adev);
|
||||
void (*ras_fini)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
struct amdgpu_nbio_funcs {
|
||||
const struct nbio_hdp_flush_reg *hdp_flush_reg;
|
||||
u32 (*get_hdp_flush_req_offset)(struct amdgpu_device *adev);
|
||||
@ -79,13 +90,6 @@ struct amdgpu_nbio_funcs {
|
||||
void (*ih_control)(struct amdgpu_device *adev);
|
||||
void (*init_registers)(struct amdgpu_device *adev);
|
||||
void (*remap_hdp_registers)(struct amdgpu_device *adev);
|
||||
void (*handle_ras_controller_intr_no_bifring)(struct amdgpu_device *adev);
|
||||
void (*handle_ras_err_event_athub_intr_no_bifring)(struct amdgpu_device *adev);
|
||||
int (*init_ras_controller_interrupt)(struct amdgpu_device *adev);
|
||||
int (*init_ras_err_event_athub_interrupt)(struct amdgpu_device *adev);
|
||||
void (*query_ras_error_count)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
int (*ras_late_init)(struct amdgpu_device *adev);
|
||||
void (*enable_aspm)(struct amdgpu_device *adev,
|
||||
bool enable);
|
||||
void (*program_aspm)(struct amdgpu_device *adev);
|
||||
@ -97,6 +101,7 @@ struct amdgpu_nbio {
|
||||
struct amdgpu_irq_src ras_err_event_athub_irq;
|
||||
struct ras_common_if *ras_if;
|
||||
const struct amdgpu_nbio_funcs *funcs;
|
||||
const struct amdgpu_nbio_ras_funcs *ras_funcs;
|
||||
};
|
||||
|
||||
int amdgpu_nbio_ras_late_init(struct amdgpu_device *adev);
|
||||
|
@ -77,6 +77,7 @@ static void amdgpu_bo_destroy(struct ttm_buffer_object *tbo)
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev);
|
||||
struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo);
|
||||
struct amdgpu_bo_user *ubo;
|
||||
|
||||
if (bo->tbo.pin_count > 0)
|
||||
amdgpu_bo_subtract_pin_size(bo);
|
||||
@ -94,7 +95,11 @@ static void amdgpu_bo_destroy(struct ttm_buffer_object *tbo)
|
||||
}
|
||||
amdgpu_bo_unref(&bo->parent);
|
||||
|
||||
kfree(bo->metadata);
|
||||
if (bo->tbo.type == ttm_bo_type_device) {
|
||||
ubo = to_amdgpu_bo_user(bo);
|
||||
kfree(ubo->metadata);
|
||||
}
|
||||
|
||||
kfree(bo);
|
||||
}
|
||||
|
||||
@ -248,6 +253,7 @@ int amdgpu_bo_create_reserved(struct amdgpu_device *adev,
|
||||
bp.flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
|
||||
bp.type = ttm_bo_type_kernel;
|
||||
bp.resv = NULL;
|
||||
bp.bo_ptr_size = sizeof(struct amdgpu_bo);
|
||||
|
||||
if (!*bo_ptr) {
|
||||
r = amdgpu_bo_create(adev, &bp, bo_ptr);
|
||||
@ -543,9 +549,10 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev,
|
||||
if (!amdgpu_bo_validate_size(adev, size, bp->domain))
|
||||
return -ENOMEM;
|
||||
|
||||
*bo_ptr = NULL;
|
||||
BUG_ON(bp->bo_ptr_size < sizeof(struct amdgpu_bo));
|
||||
|
||||
bo = kzalloc(sizeof(struct amdgpu_bo), GFP_KERNEL);
|
||||
*bo_ptr = NULL;
|
||||
bo = kzalloc(bp->bo_ptr_size, GFP_KERNEL);
|
||||
if (bo == NULL)
|
||||
return -ENOMEM;
|
||||
drm_gem_private_object_init(adev_to_drm(adev), &bo->tbo.base, size);
|
||||
@ -635,6 +642,7 @@ static int amdgpu_bo_create_shadow(struct amdgpu_device *adev,
|
||||
AMDGPU_GEM_CREATE_SHADOW;
|
||||
bp.type = ttm_bo_type_kernel;
|
||||
bp.resv = bo->tbo.base.resv;
|
||||
bp.bo_ptr_size = sizeof(struct amdgpu_bo);
|
||||
|
||||
r = amdgpu_bo_do_create(adev, &bp, &bo->shadow);
|
||||
if (!r) {
|
||||
@ -669,6 +677,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
|
||||
int r;
|
||||
|
||||
bp->flags = bp->flags & ~AMDGPU_GEM_CREATE_SHADOW;
|
||||
|
||||
r = amdgpu_bo_do_create(adev, bp, bo_ptr);
|
||||
if (r)
|
||||
return r;
|
||||
@ -690,6 +699,34 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_bo_create_user - create an &amdgpu_bo_user buffer object
|
||||
* @adev: amdgpu device object
|
||||
* @bp: parameters to be used for the buffer object
|
||||
* @ubo_ptr: pointer to the buffer object pointer
|
||||
*
|
||||
* Create a BO to be used by user application;
|
||||
*
|
||||
* Returns:
|
||||
* 0 for success or a negative error code on failure.
|
||||
*/
|
||||
|
||||
int amdgpu_bo_create_user(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_param *bp,
|
||||
struct amdgpu_bo_user **ubo_ptr)
|
||||
{
|
||||
struct amdgpu_bo *bo_ptr;
|
||||
int r;
|
||||
|
||||
bp->flags = bp->flags & ~AMDGPU_GEM_CREATE_SHADOW;
|
||||
bp->bo_ptr_size = sizeof(struct amdgpu_bo_user);
|
||||
r = amdgpu_bo_do_create(adev, bp, &bo_ptr);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
*ubo_ptr = to_amdgpu_bo_user(bo_ptr);
|
||||
return r;
|
||||
}
|
||||
/**
|
||||
* amdgpu_bo_validate - validate an &amdgpu_bo buffer object
|
||||
* @bo: pointer to the buffer object
|
||||
@ -1024,13 +1061,10 @@ int amdgpu_bo_evict_vram(struct amdgpu_device *adev)
|
||||
{
|
||||
struct ttm_resource_manager *man;
|
||||
|
||||
/* late 2.6.33 fix IGP hibernate - we need pm ops to do this correct */
|
||||
#ifndef CONFIG_HIBERNATION
|
||||
if (adev->flags & AMD_IS_APU) {
|
||||
/* Useless to evict on IGP chips */
|
||||
if (adev->in_s3 && (adev->flags & AMD_IS_APU)) {
|
||||
/* No need to evict vram on APUs for suspend to ram */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM);
|
||||
return ttm_resource_manager_evict_all(&adev->mman.bdev, man);
|
||||
@ -1095,25 +1129,6 @@ void amdgpu_bo_fini(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_bo_fbdev_mmap - mmap fbdev memory
|
||||
* @bo: &amdgpu_bo buffer object
|
||||
* @vma: vma as input from the fbdev mmap method
|
||||
*
|
||||
* Calls ttm_fbdev_mmap() to mmap fbdev memory if it is backed by a bo.
|
||||
*
|
||||
* Returns:
|
||||
* 0 for success or a negative error code on failure.
|
||||
*/
|
||||
int amdgpu_bo_fbdev_mmap(struct amdgpu_bo *bo,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
if (vma->vm_pgoff != 0)
|
||||
return -EACCES;
|
||||
|
||||
return ttm_bo_mmap_obj(vma, &bo->tbo);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_bo_set_tiling_flags - set tiling flags
|
||||
* @bo: &amdgpu_bo buffer object
|
||||
@ -1128,12 +1143,15 @@ int amdgpu_bo_fbdev_mmap(struct amdgpu_bo *bo,
|
||||
int amdgpu_bo_set_tiling_flags(struct amdgpu_bo *bo, u64 tiling_flags)
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
struct amdgpu_bo_user *ubo;
|
||||
|
||||
BUG_ON(bo->tbo.type == ttm_bo_type_kernel);
|
||||
if (adev->family <= AMDGPU_FAMILY_CZ &&
|
||||
AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT) > 6)
|
||||
return -EINVAL;
|
||||
|
||||
bo->tiling_flags = tiling_flags;
|
||||
ubo = to_amdgpu_bo_user(bo);
|
||||
ubo->tiling_flags = tiling_flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1147,10 +1165,14 @@ int amdgpu_bo_set_tiling_flags(struct amdgpu_bo *bo, u64 tiling_flags)
|
||||
*/
|
||||
void amdgpu_bo_get_tiling_flags(struct amdgpu_bo *bo, u64 *tiling_flags)
|
||||
{
|
||||
struct amdgpu_bo_user *ubo;
|
||||
|
||||
BUG_ON(bo->tbo.type == ttm_bo_type_kernel);
|
||||
dma_resv_assert_held(bo->tbo.base.resv);
|
||||
ubo = to_amdgpu_bo_user(bo);
|
||||
|
||||
if (tiling_flags)
|
||||
*tiling_flags = bo->tiling_flags;
|
||||
*tiling_flags = ubo->tiling_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1169,13 +1191,16 @@ void amdgpu_bo_get_tiling_flags(struct amdgpu_bo *bo, u64 *tiling_flags)
|
||||
int amdgpu_bo_set_metadata (struct amdgpu_bo *bo, void *metadata,
|
||||
uint32_t metadata_size, uint64_t flags)
|
||||
{
|
||||
struct amdgpu_bo_user *ubo;
|
||||
void *buffer;
|
||||
|
||||
BUG_ON(bo->tbo.type == ttm_bo_type_kernel);
|
||||
ubo = to_amdgpu_bo_user(bo);
|
||||
if (!metadata_size) {
|
||||
if (bo->metadata_size) {
|
||||
kfree(bo->metadata);
|
||||
bo->metadata = NULL;
|
||||
bo->metadata_size = 0;
|
||||
if (ubo->metadata_size) {
|
||||
kfree(ubo->metadata);
|
||||
ubo->metadata = NULL;
|
||||
ubo->metadata_size = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1187,10 +1212,10 @@ int amdgpu_bo_set_metadata (struct amdgpu_bo *bo, void *metadata,
|
||||
if (buffer == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
kfree(bo->metadata);
|
||||
bo->metadata_flags = flags;
|
||||
bo->metadata = buffer;
|
||||
bo->metadata_size = metadata_size;
|
||||
kfree(ubo->metadata);
|
||||
ubo->metadata_flags = flags;
|
||||
ubo->metadata = buffer;
|
||||
ubo->metadata_size = metadata_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1214,21 +1239,25 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
|
||||
size_t buffer_size, uint32_t *metadata_size,
|
||||
uint64_t *flags)
|
||||
{
|
||||
struct amdgpu_bo_user *ubo;
|
||||
|
||||
if (!buffer && !metadata_size)
|
||||
return -EINVAL;
|
||||
|
||||
BUG_ON(bo->tbo.type == ttm_bo_type_kernel);
|
||||
ubo = to_amdgpu_bo_user(bo);
|
||||
if (buffer) {
|
||||
if (buffer_size < bo->metadata_size)
|
||||
if (buffer_size < ubo->metadata_size)
|
||||
return -EINVAL;
|
||||
|
||||
if (bo->metadata_size)
|
||||
memcpy(buffer, bo->metadata, bo->metadata_size);
|
||||
if (ubo->metadata_size)
|
||||
memcpy(buffer, ubo->metadata, ubo->metadata_size);
|
||||
}
|
||||
|
||||
if (metadata_size)
|
||||
*metadata_size = bo->metadata_size;
|
||||
*metadata_size = ubo->metadata_size;
|
||||
if (flags)
|
||||
*flags = bo->metadata_flags;
|
||||
*flags = ubo->metadata_flags;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -37,9 +37,12 @@
|
||||
#define AMDGPU_BO_INVALID_OFFSET LONG_MAX
|
||||
#define AMDGPU_BO_MAX_PLACEMENTS 3
|
||||
|
||||
#define to_amdgpu_bo_user(abo) container_of((abo), struct amdgpu_bo_user, bo)
|
||||
|
||||
struct amdgpu_bo_param {
|
||||
unsigned long size;
|
||||
int byte_align;
|
||||
u32 bo_ptr_size;
|
||||
u32 domain;
|
||||
u32 preferred_domain;
|
||||
u64 flags;
|
||||
@ -89,10 +92,6 @@ struct amdgpu_bo {
|
||||
struct ttm_buffer_object tbo;
|
||||
struct ttm_bo_kmap_obj kmap;
|
||||
u64 flags;
|
||||
u64 tiling_flags;
|
||||
u64 metadata_flags;
|
||||
void *metadata;
|
||||
u32 metadata_size;
|
||||
unsigned prime_shared_count;
|
||||
/* per VM structure for page tables and with virtual addresses */
|
||||
struct amdgpu_vm_bo_base *vm_bo;
|
||||
@ -111,6 +110,15 @@ struct amdgpu_bo {
|
||||
struct kgd_mem *kfd_bo;
|
||||
};
|
||||
|
||||
struct amdgpu_bo_user {
|
||||
struct amdgpu_bo bo;
|
||||
u64 tiling_flags;
|
||||
u64 metadata_flags;
|
||||
void *metadata;
|
||||
u32 metadata_size;
|
||||
|
||||
};
|
||||
|
||||
static inline struct amdgpu_bo *ttm_to_amdgpu_bo(struct ttm_buffer_object *tbo)
|
||||
{
|
||||
return container_of(tbo, struct amdgpu_bo, tbo);
|
||||
@ -254,6 +262,9 @@ int amdgpu_bo_create_kernel(struct amdgpu_device *adev,
|
||||
int amdgpu_bo_create_kernel_at(struct amdgpu_device *adev,
|
||||
uint64_t offset, uint64_t size, uint32_t domain,
|
||||
struct amdgpu_bo **bo_ptr, void **cpu_addr);
|
||||
int amdgpu_bo_create_user(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_param *bp,
|
||||
struct amdgpu_bo_user **ubo_ptr);
|
||||
void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr,
|
||||
void **cpu_addr);
|
||||
int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr);
|
||||
@ -268,8 +279,6 @@ void amdgpu_bo_unpin(struct amdgpu_bo *bo);
|
||||
int amdgpu_bo_evict_vram(struct amdgpu_device *adev);
|
||||
int amdgpu_bo_init(struct amdgpu_device *adev);
|
||||
void amdgpu_bo_fini(struct amdgpu_device *adev);
|
||||
int amdgpu_bo_fbdev_mmap(struct amdgpu_bo *bo,
|
||||
struct vm_area_struct *vma);
|
||||
int amdgpu_bo_set_tiling_flags(struct amdgpu_bo *bo, u64 tiling_flags);
|
||||
void amdgpu_bo_get_tiling_flags(struct amdgpu_bo *bo, u64 *tiling_flags);
|
||||
int amdgpu_bo_set_metadata (struct amdgpu_bo *bo, void *metadata,
|
||||
|
@ -556,6 +556,24 @@ int psp_get_fw_attestation_records_addr(struct psp_context *psp,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psp_boot_config_set(struct amdgpu_device *adev)
|
||||
{
|
||||
struct psp_context *psp = &adev->psp;
|
||||
struct psp_gfx_cmd_resp *cmd = psp->cmd;
|
||||
|
||||
if (adev->asic_type != CHIP_SIENNA_CICHLID)
|
||||
return 0;
|
||||
|
||||
memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
|
||||
|
||||
cmd->cmd_id = GFX_CMD_ID_BOOT_CFG;
|
||||
cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_SET;
|
||||
cmd->cmd.boot_cfg.boot_config = BOOT_CONFIG_GECC;
|
||||
cmd->cmd.boot_cfg.boot_config_valid = BOOT_CONFIG_GECC;
|
||||
|
||||
return psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
|
||||
}
|
||||
|
||||
static int psp_rl_load(struct amdgpu_device *adev)
|
||||
{
|
||||
struct psp_context *psp = &adev->psp;
|
||||
@ -1912,6 +1930,11 @@ static int psp_hw_start(struct psp_context *psp)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = psp_boot_config_set(adev);
|
||||
if (ret) {
|
||||
DRM_WARN("PSP set boot config@\n");
|
||||
}
|
||||
|
||||
ret = psp_tmr_init(psp);
|
||||
if (ret) {
|
||||
DRM_ERROR("PSP tmr init failed!\n");
|
||||
@ -2146,9 +2169,13 @@ static int psp_load_smu_fw(struct psp_context *psp)
|
||||
if (!ucode->fw || amdgpu_sriov_vf(psp->adev))
|
||||
return 0;
|
||||
|
||||
|
||||
if (amdgpu_in_reset(adev) && ras && ras->supported &&
|
||||
adev->asic_type == CHIP_ARCTURUS) {
|
||||
if ((amdgpu_in_reset(adev) &&
|
||||
ras && ras->supported &&
|
||||
(adev->asic_type == CHIP_ARCTURUS ||
|
||||
adev->asic_type == CHIP_VEGA20)) ||
|
||||
(adev->in_runpm &&
|
||||
adev->asic_type >= CHIP_NAVI10 &&
|
||||
adev->asic_type <= CHIP_NAVI12)) {
|
||||
ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD);
|
||||
if (ret) {
|
||||
DRM_WARN("Failed to set MP1 state prepare for reload\n");
|
||||
@ -2201,6 +2228,22 @@ static bool fw_load_skip_check(struct psp_context *psp,
|
||||
return false;
|
||||
}
|
||||
|
||||
int psp_load_fw_list(struct psp_context *psp,
|
||||
struct amdgpu_firmware_info **ucode_list, int ucode_count)
|
||||
{
|
||||
int ret = 0, i;
|
||||
struct amdgpu_firmware_info *ucode;
|
||||
|
||||
for (i = 0; i < ucode_count; ++i) {
|
||||
ucode = ucode_list[i];
|
||||
psp_print_fw_hdr(psp, ucode);
|
||||
ret = psp_execute_np_fw_load(psp, ucode);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int psp_np_fw_load(struct psp_context *psp)
|
||||
{
|
||||
int i, ret;
|
||||
@ -2967,7 +3010,7 @@ static ssize_t psp_usbc_pd_fw_sysfs_read(struct device *dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%x\n", fw_ver);
|
||||
return sysfs_emit(buf, "%x\n", fw_ver);
|
||||
}
|
||||
|
||||
static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
|
||||
|
@ -420,4 +420,7 @@ int psp_init_ta_microcode(struct psp_context *psp,
|
||||
const char *chip_name);
|
||||
int psp_get_fw_attestation_records_addr(struct psp_context *psp,
|
||||
uint64_t *output_ptr);
|
||||
|
||||
int psp_load_fw_list(struct psp_context *psp,
|
||||
struct amdgpu_firmware_info **ucode_list, int ucode_count);
|
||||
#endif
|
||||
|
@ -99,6 +99,49 @@ static bool amdgpu_ras_get_error_query_ready(struct amdgpu_device *adev)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int amdgpu_reserve_page_direct(struct amdgpu_device *adev, uint64_t address)
|
||||
{
|
||||
struct ras_err_data err_data = {0, 0, 0, NULL};
|
||||
struct eeprom_table_record err_rec;
|
||||
|
||||
if ((address >= adev->gmc.mc_vram_size) ||
|
||||
(address >= RAS_UMC_INJECT_ADDR_LIMIT)) {
|
||||
dev_warn(adev->dev,
|
||||
"RAS WARN: input address 0x%llx is invalid.\n",
|
||||
address);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (amdgpu_ras_check_bad_page(adev, address)) {
|
||||
dev_warn(adev->dev,
|
||||
"RAS WARN: 0x%llx has been marked as bad page!\n",
|
||||
address);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&err_rec, 0x0, sizeof(struct eeprom_table_record));
|
||||
|
||||
err_rec.address = address;
|
||||
err_rec.retired_page = address >> AMDGPU_GPU_PAGE_SHIFT;
|
||||
err_rec.ts = (uint64_t)ktime_get_real_seconds();
|
||||
err_rec.err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE;
|
||||
|
||||
err_data.err_addr = &err_rec;
|
||||
err_data.err_addr_cnt = 1;
|
||||
|
||||
if (amdgpu_bad_page_threshold != 0) {
|
||||
amdgpu_ras_add_bad_pages(adev, err_data.err_addr,
|
||||
err_data.err_addr_cnt);
|
||||
amdgpu_ras_save_bad_pages(adev);
|
||||
}
|
||||
|
||||
dev_warn(adev->dev, "WARNING: THIS IS ONLY FOR TEST PURPOSES AND WILL CORRUPT RAS EEPROM\n");
|
||||
dev_warn(adev->dev, "Clear EEPROM:\n");
|
||||
dev_warn(adev->dev, " echo 1 > /sys/kernel/debug/dri/0/ras/ras_eeprom_reset\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_ras_debugfs_read(struct file *f, char __user *buf,
|
||||
size_t size, loff_t *pos)
|
||||
{
|
||||
@ -178,11 +221,25 @@ static int amdgpu_ras_debugfs_ctrl_parse_data(struct file *f,
|
||||
op = 1;
|
||||
else if (sscanf(str, "inject %32s %8s", block_name, err) == 2)
|
||||
op = 2;
|
||||
else if (sscanf(str, "retire_page") == 0)
|
||||
op = 3;
|
||||
else if (str[0] && str[1] && str[2] && str[3])
|
||||
/* ascii string, but commands are not matched. */
|
||||
return -EINVAL;
|
||||
|
||||
if (op != -1) {
|
||||
|
||||
if (op == 3) {
|
||||
if (sscanf(str, "%*s %llu", &address) != 1)
|
||||
if (sscanf(str, "%*s 0x%llx", &address) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
data->op = op;
|
||||
data->inject.address = address;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (amdgpu_ras_find_block_id_by_name(block_name, &block_id))
|
||||
return -EINVAL;
|
||||
|
||||
@ -310,6 +367,16 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user *
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
if (data.op == 3)
|
||||
{
|
||||
ret = amdgpu_reserve_page_direct(adev, data.inject.address);
|
||||
|
||||
if (ret)
|
||||
return size;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!amdgpu_ras_is_supported(adev, data.head.block))
|
||||
return -EINVAL;
|
||||
|
||||
@ -431,15 +498,13 @@ static ssize_t amdgpu_ras_sysfs_read(struct device *dev,
|
||||
};
|
||||
|
||||
if (!amdgpu_ras_get_error_query_ready(obj->adev))
|
||||
return snprintf(buf, PAGE_SIZE,
|
||||
"Query currently inaccessible\n");
|
||||
return sysfs_emit(buf, "Query currently inaccessible\n");
|
||||
|
||||
if (amdgpu_ras_query_error_status(obj->adev, &info))
|
||||
return -EINVAL;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s: %lu\n%s: %lu\n",
|
||||
"ue", info.ue_count,
|
||||
"ce", info.ce_count);
|
||||
return sysfs_emit(buf, "%s: %lu\n%s: %lu\n", "ue", info.ue_count,
|
||||
"ce", info.ce_count);
|
||||
}
|
||||
|
||||
/* obj begin */
|
||||
@ -449,11 +514,10 @@ static ssize_t amdgpu_ras_sysfs_read(struct device *dev,
|
||||
|
||||
static inline void put_obj(struct ras_manager *obj)
|
||||
{
|
||||
if (obj && --obj->use == 0)
|
||||
if (obj && (--obj->use == 0))
|
||||
list_del(&obj->node);
|
||||
if (obj && obj->use < 0) {
|
||||
DRM_ERROR("RAS ERROR: Unbalance obj(%s) use\n", obj->head.name);
|
||||
}
|
||||
if (obj && (obj->use < 0))
|
||||
DRM_ERROR("RAS ERROR: Unbalance obj(%s) use\n", obj->head.name);
|
||||
}
|
||||
|
||||
/* make one obj and return it. */
|
||||
@ -777,13 +841,15 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
|
||||
|
||||
switch (info->head.block) {
|
||||
case AMDGPU_RAS_BLOCK__UMC:
|
||||
if (adev->umc.funcs->query_ras_error_count)
|
||||
adev->umc.funcs->query_ras_error_count(adev, &err_data);
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->query_ras_error_count)
|
||||
adev->umc.ras_funcs->query_ras_error_count(adev, &err_data);
|
||||
/* umc query_ras_error_address is also responsible for clearing
|
||||
* error status
|
||||
*/
|
||||
if (adev->umc.funcs->query_ras_error_address)
|
||||
adev->umc.funcs->query_ras_error_address(adev, &err_data);
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->query_ras_error_address)
|
||||
adev->umc.ras_funcs->query_ras_error_address(adev, &err_data);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__SDMA:
|
||||
if (adev->sdma.funcs->query_ras_error_count) {
|
||||
@ -793,25 +859,32 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev,
|
||||
}
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__GFX:
|
||||
if (adev->gfx.funcs->query_ras_error_count)
|
||||
adev->gfx.funcs->query_ras_error_count(adev, &err_data);
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->query_ras_error_count)
|
||||
adev->gfx.ras_funcs->query_ras_error_count(adev, &err_data);
|
||||
|
||||
if (adev->gfx.funcs->query_ras_error_status)
|
||||
adev->gfx.funcs->query_ras_error_status(adev);
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->query_ras_error_status)
|
||||
adev->gfx.ras_funcs->query_ras_error_status(adev);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__MMHUB:
|
||||
if (adev->mmhub.funcs->query_ras_error_count)
|
||||
adev->mmhub.funcs->query_ras_error_count(adev, &err_data);
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->query_ras_error_count)
|
||||
adev->mmhub.ras_funcs->query_ras_error_count(adev, &err_data);
|
||||
|
||||
if (adev->mmhub.funcs->query_ras_error_status)
|
||||
adev->mmhub.funcs->query_ras_error_status(adev);
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->query_ras_error_status)
|
||||
adev->mmhub.ras_funcs->query_ras_error_status(adev);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__PCIE_BIF:
|
||||
if (adev->nbio.funcs->query_ras_error_count)
|
||||
adev->nbio.funcs->query_ras_error_count(adev, &err_data);
|
||||
if (adev->nbio.ras_funcs &&
|
||||
adev->nbio.ras_funcs->query_ras_error_count)
|
||||
adev->nbio.ras_funcs->query_ras_error_count(adev, &err_data);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__XGMI_WAFL:
|
||||
amdgpu_xgmi_query_ras_error_count(adev, &err_data);
|
||||
if (adev->gmc.xgmi.ras_funcs &&
|
||||
adev->gmc.xgmi.ras_funcs->query_ras_error_count)
|
||||
adev->gmc.xgmi.ras_funcs->query_ras_error_count(adev, &err_data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -848,15 +921,18 @@ int amdgpu_ras_reset_error_status(struct amdgpu_device *adev,
|
||||
|
||||
switch (block) {
|
||||
case AMDGPU_RAS_BLOCK__GFX:
|
||||
if (adev->gfx.funcs->reset_ras_error_count)
|
||||
adev->gfx.funcs->reset_ras_error_count(adev);
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->reset_ras_error_count)
|
||||
adev->gfx.ras_funcs->reset_ras_error_count(adev);
|
||||
|
||||
if (adev->gfx.funcs->reset_ras_error_status)
|
||||
adev->gfx.funcs->reset_ras_error_status(adev);
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->reset_ras_error_status)
|
||||
adev->gfx.ras_funcs->reset_ras_error_status(adev);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__MMHUB:
|
||||
if (adev->mmhub.funcs->reset_ras_error_count)
|
||||
adev->mmhub.funcs->reset_ras_error_count(adev);
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->reset_ras_error_count)
|
||||
adev->mmhub.ras_funcs->reset_ras_error_count(adev);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__SDMA:
|
||||
if (adev->sdma.funcs->reset_ras_error_count)
|
||||
@ -921,12 +997,14 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev,
|
||||
|
||||
switch (info->head.block) {
|
||||
case AMDGPU_RAS_BLOCK__GFX:
|
||||
if (adev->gfx.funcs->ras_error_inject)
|
||||
ret = adev->gfx.funcs->ras_error_inject(adev, info);
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->ras_error_inject)
|
||||
ret = adev->gfx.ras_funcs->ras_error_inject(adev, info);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__UMC:
|
||||
case AMDGPU_RAS_BLOCK__SDMA:
|
||||
case AMDGPU_RAS_BLOCK__MMHUB:
|
||||
case AMDGPU_RAS_BLOCK__PCIE_BIF:
|
||||
ret = psp_ras_trigger_error(&adev->psp, &block_info);
|
||||
@ -1508,12 +1586,14 @@ static void amdgpu_ras_error_status_query(struct amdgpu_device *adev,
|
||||
*/
|
||||
switch (info->head.block) {
|
||||
case AMDGPU_RAS_BLOCK__GFX:
|
||||
if (adev->gfx.funcs->query_ras_error_status)
|
||||
adev->gfx.funcs->query_ras_error_status(adev);
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->query_ras_error_status)
|
||||
adev->gfx.ras_funcs->query_ras_error_status(adev);
|
||||
break;
|
||||
case AMDGPU_RAS_BLOCK__MMHUB:
|
||||
if (adev->mmhub.funcs->query_ras_error_status)
|
||||
adev->mmhub.funcs->query_ras_error_status(adev);
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->query_ras_error_status)
|
||||
adev->mmhub.ras_funcs->query_ras_error_status(adev);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -1933,15 +2013,13 @@ int amdgpu_ras_request_reset_on_boot(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_ras_check_asic_type(struct amdgpu_device *adev)
|
||||
static bool amdgpu_ras_asic_supported(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->asic_type != CHIP_VEGA10 &&
|
||||
adev->asic_type != CHIP_VEGA20 &&
|
||||
adev->asic_type != CHIP_ARCTURUS &&
|
||||
adev->asic_type != CHIP_SIENNA_CICHLID)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
return adev->asic_type == CHIP_VEGA10 ||
|
||||
adev->asic_type == CHIP_VEGA20 ||
|
||||
adev->asic_type == CHIP_ARCTURUS ||
|
||||
adev->asic_type == CHIP_ALDEBARAN ||
|
||||
adev->asic_type == CHIP_SIENNA_CICHLID;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1960,22 +2038,32 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev,
|
||||
*supported = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(adev) || !adev->is_atom_fw ||
|
||||
amdgpu_ras_check_asic_type(adev))
|
||||
!amdgpu_ras_asic_supported(adev))
|
||||
return;
|
||||
|
||||
if (amdgpu_atomfirmware_mem_ecc_supported(adev)) {
|
||||
dev_info(adev->dev, "MEM ECC is active.\n");
|
||||
*hw_supported |= (1 << AMDGPU_RAS_BLOCK__UMC |
|
||||
1 << AMDGPU_RAS_BLOCK__DF);
|
||||
} else
|
||||
dev_info(adev->dev, "MEM ECC is not presented.\n");
|
||||
if (!adev->gmc.xgmi.connected_to_cpu) {
|
||||
if (amdgpu_atomfirmware_mem_ecc_supported(adev)) {
|
||||
dev_info(adev->dev, "MEM ECC is active.\n");
|
||||
*hw_supported |= (1 << AMDGPU_RAS_BLOCK__UMC |
|
||||
1 << AMDGPU_RAS_BLOCK__DF);
|
||||
} else {
|
||||
dev_info(adev->dev, "MEM ECC is not presented.\n");
|
||||
}
|
||||
|
||||
if (amdgpu_atomfirmware_sram_ecc_supported(adev)) {
|
||||
dev_info(adev->dev, "SRAM ECC is active.\n");
|
||||
*hw_supported |= ~(1 << AMDGPU_RAS_BLOCK__UMC |
|
||||
1 << AMDGPU_RAS_BLOCK__DF);
|
||||
} else
|
||||
dev_info(adev->dev, "SRAM ECC is not presented.\n");
|
||||
if (amdgpu_atomfirmware_sram_ecc_supported(adev)) {
|
||||
dev_info(adev->dev, "SRAM ECC is active.\n");
|
||||
*hw_supported |= ~(1 << AMDGPU_RAS_BLOCK__UMC |
|
||||
1 << AMDGPU_RAS_BLOCK__DF);
|
||||
} else {
|
||||
dev_info(adev->dev, "SRAM ECC is not presented.\n");
|
||||
}
|
||||
} else {
|
||||
/* driver only manages a few IP blocks RAS feature
|
||||
* when GPU is connected cpu through XGMI */
|
||||
*hw_supported |= (1 << AMDGPU_RAS_BLOCK__GFX |
|
||||
1 << AMDGPU_RAS_BLOCK__SDMA |
|
||||
1 << AMDGPU_RAS_BLOCK__MMHUB);
|
||||
}
|
||||
|
||||
/* hw_supported needs to be aligned with RAS block mask. */
|
||||
*hw_supported &= AMDGPU_RAS_BLOCK_MASK;
|
||||
@ -2024,14 +2112,31 @@ int amdgpu_ras_init(struct amdgpu_device *adev)
|
||||
/* Might need get this flag from vbios. */
|
||||
con->flags = RAS_DEFAULT_FLAGS;
|
||||
|
||||
if (adev->nbio.funcs->init_ras_controller_interrupt) {
|
||||
r = adev->nbio.funcs->init_ras_controller_interrupt(adev);
|
||||
/* initialize nbio ras function ahead of any other
|
||||
* ras functions so hardware fatal error interrupt
|
||||
* can be enabled as early as possible */
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA20:
|
||||
case CHIP_ARCTURUS:
|
||||
case CHIP_ALDEBARAN:
|
||||
if (!adev->gmc.xgmi.connected_to_cpu)
|
||||
adev->nbio.ras_funcs = &nbio_v7_4_ras_funcs;
|
||||
break;
|
||||
default:
|
||||
/* nbio ras is not available */
|
||||
break;
|
||||
}
|
||||
|
||||
if (adev->nbio.ras_funcs &&
|
||||
adev->nbio.ras_funcs->init_ras_controller_interrupt) {
|
||||
r = adev->nbio.ras_funcs->init_ras_controller_interrupt(adev);
|
||||
if (r)
|
||||
goto release_con;
|
||||
}
|
||||
|
||||
if (adev->nbio.funcs->init_ras_err_event_athub_interrupt) {
|
||||
r = adev->nbio.funcs->init_ras_err_event_athub_interrupt(adev);
|
||||
if (adev->nbio.ras_funcs &&
|
||||
adev->nbio.ras_funcs->init_ras_err_event_athub_interrupt) {
|
||||
r = adev->nbio.ras_funcs->init_ras_err_event_athub_interrupt(adev);
|
||||
if (r)
|
||||
goto release_con;
|
||||
}
|
||||
@ -2052,6 +2157,32 @@ release_con:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int amdgpu_persistent_edc_harvesting_supported(struct amdgpu_device *adev)
|
||||
{
|
||||
if (adev->gmc.xgmi.connected_to_cpu)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_persistent_edc_harvesting(struct amdgpu_device *adev,
|
||||
struct ras_common_if *ras_block)
|
||||
{
|
||||
struct ras_query_if info = {
|
||||
.head = *ras_block,
|
||||
};
|
||||
|
||||
if (!amdgpu_persistent_edc_harvesting_supported(adev))
|
||||
return 0;
|
||||
|
||||
if (amdgpu_ras_query_error_status(adev, &info) != 0)
|
||||
DRM_WARN("RAS init harvest failure");
|
||||
|
||||
if (amdgpu_ras_reset_error_status(adev, ras_block->block) != 0)
|
||||
DRM_WARN("RAS init harvest reset failure");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* helper function to handle common stuff in ip late init phase */
|
||||
int amdgpu_ras_late_init(struct amdgpu_device *adev,
|
||||
struct ras_common_if *ras_block,
|
||||
@ -2081,6 +2212,9 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev,
|
||||
return r;
|
||||
}
|
||||
|
||||
/* check for errors on warm reset edc persisant supported ASIC */
|
||||
amdgpu_persistent_edc_harvesting(adev, ras_block);
|
||||
|
||||
/* in resume phase, no need to create ras fs node */
|
||||
if (adev->in_suspend || amdgpu_in_reset(adev))
|
||||
return 0;
|
||||
|
@ -31,6 +31,7 @@
|
||||
#define EEPROM_I2C_TARGET_ADDR_ARCTURUS 0xA8
|
||||
#define EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342 0xA0
|
||||
#define EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID 0xA0
|
||||
#define EEPROM_I2C_TARGET_ADDR_ALDEBARAN 0xA0
|
||||
|
||||
/*
|
||||
* The 2 macros bellow represent the actual size in bytes that
|
||||
@ -64,7 +65,8 @@ static bool __is_ras_eeprom_supported(struct amdgpu_device *adev)
|
||||
{
|
||||
if ((adev->asic_type == CHIP_VEGA20) ||
|
||||
(adev->asic_type == CHIP_ARCTURUS) ||
|
||||
(adev->asic_type == CHIP_SIENNA_CICHLID))
|
||||
(adev->asic_type == CHIP_SIENNA_CICHLID) ||
|
||||
(adev->asic_type == CHIP_ALDEBARAN))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -106,6 +108,10 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
|
||||
*i2c_addr = EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID;
|
||||
break;
|
||||
|
||||
case CHIP_ALDEBARAN:
|
||||
*i2c_addr = EEPROM_I2C_TARGET_ADDR_ALDEBARAN;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ static inline void amdgpu_res_first(struct ttm_resource *res,
|
||||
BUG_ON(start + size > res->num_pages << PAGE_SHIFT);
|
||||
|
||||
node = res->mm_node;
|
||||
while (start > node->size << PAGE_SHIFT)
|
||||
while (start >= node->size << PAGE_SHIFT)
|
||||
start -= node++->size << PAGE_SHIFT;
|
||||
|
||||
cur->start = (node->start << PAGE_SHIFT) + start;
|
||||
|
98
drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
Normal file
98
drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2021 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "amdgpu_reset.h"
|
||||
#include "aldebaran.h"
|
||||
|
||||
int amdgpu_reset_add_handler(struct amdgpu_reset_control *reset_ctl,
|
||||
struct amdgpu_reset_handler *handler)
|
||||
{
|
||||
/* TODO: Check if handler exists? */
|
||||
list_add_tail(&handler->handler_list, &reset_ctl->reset_handlers);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_reset_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_ALDEBARAN:
|
||||
ret = aldebaran_reset_init(adev);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int amdgpu_reset_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_ALDEBARAN:
|
||||
ret = aldebaran_reset_fini(adev);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int amdgpu_reset_prepare_hwcontext(struct amdgpu_device *adev,
|
||||
struct amdgpu_reset_context *reset_context)
|
||||
{
|
||||
struct amdgpu_reset_handler *reset_handler = NULL;
|
||||
|
||||
if (adev->reset_cntl && adev->reset_cntl->get_reset_handler)
|
||||
reset_handler = adev->reset_cntl->get_reset_handler(
|
||||
adev->reset_cntl, reset_context);
|
||||
if (!reset_handler)
|
||||
return -ENOSYS;
|
||||
|
||||
return reset_handler->prepare_hwcontext(adev->reset_cntl,
|
||||
reset_context);
|
||||
}
|
||||
|
||||
int amdgpu_reset_perform_reset(struct amdgpu_device *adev,
|
||||
struct amdgpu_reset_context *reset_context)
|
||||
{
|
||||
int ret;
|
||||
struct amdgpu_reset_handler *reset_handler = NULL;
|
||||
|
||||
if (adev->reset_cntl)
|
||||
reset_handler = adev->reset_cntl->get_reset_handler(
|
||||
adev->reset_cntl, reset_context);
|
||||
if (!reset_handler)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = reset_handler->perform_reset(adev->reset_cntl, reset_context);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return reset_handler->restore_hwcontext(adev->reset_cntl,
|
||||
reset_context);
|
||||
}
|
85
drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h
Normal file
85
drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2021 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __AMDGPU_RESET_H__
|
||||
#define __AMDGPU_RESET_H__
|
||||
|
||||
#include "amdgpu.h"
|
||||
|
||||
enum AMDGPU_RESET_FLAGS {
|
||||
|
||||
AMDGPU_NEED_FULL_RESET = 0,
|
||||
AMDGPU_SKIP_HW_RESET = 1,
|
||||
};
|
||||
|
||||
struct amdgpu_reset_context {
|
||||
enum amd_reset_method method;
|
||||
struct amdgpu_device *reset_req_dev;
|
||||
struct amdgpu_job *job;
|
||||
struct amdgpu_hive_info *hive;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
struct amdgpu_reset_handler {
|
||||
enum amd_reset_method reset_method;
|
||||
struct list_head handler_list;
|
||||
int (*prepare_env)(struct amdgpu_reset_control *reset_ctl,
|
||||
struct amdgpu_reset_context *context);
|
||||
int (*prepare_hwcontext)(struct amdgpu_reset_control *reset_ctl,
|
||||
struct amdgpu_reset_context *context);
|
||||
int (*perform_reset)(struct amdgpu_reset_control *reset_ctl,
|
||||
struct amdgpu_reset_context *context);
|
||||
int (*restore_hwcontext)(struct amdgpu_reset_control *reset_ctl,
|
||||
struct amdgpu_reset_context *context);
|
||||
int (*restore_env)(struct amdgpu_reset_control *reset_ctl,
|
||||
struct amdgpu_reset_context *context);
|
||||
|
||||
int (*do_reset)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
struct amdgpu_reset_control {
|
||||
void *handle;
|
||||
struct work_struct reset_work;
|
||||
struct mutex reset_lock;
|
||||
struct list_head reset_handlers;
|
||||
atomic_t in_reset;
|
||||
enum amd_reset_method active_reset;
|
||||
struct amdgpu_reset_handler *(*get_reset_handler)(
|
||||
struct amdgpu_reset_control *reset_ctl,
|
||||
struct amdgpu_reset_context *context);
|
||||
void (*async_reset)(struct work_struct *work);
|
||||
};
|
||||
|
||||
int amdgpu_reset_init(struct amdgpu_device *adev);
|
||||
int amdgpu_reset_fini(struct amdgpu_device *adev);
|
||||
|
||||
int amdgpu_reset_prepare_hwcontext(struct amdgpu_device *adev,
|
||||
struct amdgpu_reset_context *reset_context);
|
||||
|
||||
int amdgpu_reset_perform_reset(struct amdgpu_device *adev,
|
||||
struct amdgpu_reset_context *reset_context);
|
||||
|
||||
int amdgpu_reset_add_handler(struct amdgpu_reset_control *reset_ctl,
|
||||
struct amdgpu_reset_handler *handler);
|
||||
|
||||
#endif
|
@ -164,7 +164,8 @@ void amdgpu_ring_undo(struct amdgpu_ring *ring)
|
||||
*/
|
||||
int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
|
||||
unsigned int max_dw, struct amdgpu_irq_src *irq_src,
|
||||
unsigned int irq_type, unsigned int hw_prio)
|
||||
unsigned int irq_type, unsigned int hw_prio,
|
||||
atomic_t *sched_score)
|
||||
{
|
||||
int r;
|
||||
int sched_hw_submission = amdgpu_sched_hw_submission;
|
||||
@ -189,7 +190,8 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
|
||||
ring->adev = adev;
|
||||
ring->idx = adev->num_rings++;
|
||||
adev->rings[ring->idx] = ring;
|
||||
r = amdgpu_fence_driver_init_ring(ring, sched_hw_submission);
|
||||
r = amdgpu_fence_driver_init_ring(ring, sched_hw_submission,
|
||||
sched_score);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -111,7 +111,8 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev);
|
||||
void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring);
|
||||
|
||||
int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
|
||||
unsigned num_hw_submission);
|
||||
unsigned num_hw_submission,
|
||||
atomic_t *sched_score);
|
||||
int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
|
||||
struct amdgpu_irq_src *irq_src,
|
||||
unsigned irq_type);
|
||||
@ -282,7 +283,8 @@ void amdgpu_ring_commit(struct amdgpu_ring *ring);
|
||||
void amdgpu_ring_undo(struct amdgpu_ring *ring);
|
||||
int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
|
||||
unsigned int ring_size, struct amdgpu_irq_src *irq_src,
|
||||
unsigned int irq_type, unsigned int prio);
|
||||
unsigned int irq_type, unsigned int prio,
|
||||
atomic_t *sched_score);
|
||||
void amdgpu_ring_fini(struct amdgpu_ring *ring);
|
||||
void amdgpu_ring_emit_reg_write_reg_wait_helper(struct amdgpu_ring *ring,
|
||||
uint32_t reg0, uint32_t val0,
|
||||
|
@ -127,7 +127,8 @@ struct amdgpu_rlc_funcs {
|
||||
void (*reset)(struct amdgpu_device *adev);
|
||||
void (*start)(struct amdgpu_device *adev);
|
||||
void (*update_spm_vmid)(struct amdgpu_device *adev, unsigned vmid);
|
||||
void (*rlcg_wreg)(struct amdgpu_device *adev, u32 offset, u32 v);
|
||||
void (*rlcg_wreg)(struct amdgpu_device *adev, u32 offset, u32 v, u32 flag);
|
||||
u32 (*rlcg_rreg)(struct amdgpu_device *adev, u32 offset, u32 flag);
|
||||
bool (*is_rlcg_access_range)(struct amdgpu_device *adev, uint32_t reg);
|
||||
};
|
||||
|
||||
|
@ -95,9 +95,7 @@ static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __u
|
||||
struct drm_device *dev = adev_to_drm(adev);
|
||||
uint32_t phy_id;
|
||||
uint32_t op;
|
||||
int i;
|
||||
char str[64];
|
||||
char i2c_output[256];
|
||||
int ret;
|
||||
|
||||
if (*pos || size > sizeof(str) - 1)
|
||||
@ -139,11 +137,9 @@ static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __u
|
||||
ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC);
|
||||
if (!ret) {
|
||||
if (securedisplay_cmd->status == TA_SECUREDISPLAY_STATUS__SUCCESS) {
|
||||
memset(i2c_output, 0, sizeof(i2c_output));
|
||||
for (i = 0; i < TA_SECUREDISPLAY_I2C_BUFFER_SIZE; i++)
|
||||
sprintf(i2c_output, "%s 0x%X", i2c_output,
|
||||
securedisplay_cmd->securedisplay_out_message.send_roi_crc.i2c_buf[i]);
|
||||
dev_info(adev->dev, "SECUREDISPLAY: I2C buffer out put is :%s\n", i2c_output);
|
||||
dev_info(adev->dev, "SECUREDISPLAY: I2C buffer out put is: %*ph\n",
|
||||
TA_SECUREDISPLAY_I2C_BUFFER_SIZE,
|
||||
securedisplay_cmd->securedisplay_out_message.send_roi_crc.i2c_buf);
|
||||
} else {
|
||||
psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status);
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev)
|
||||
bp.flags = 0;
|
||||
bp.type = ttm_bo_type_kernel;
|
||||
bp.resv = NULL;
|
||||
bp.bo_ptr_size = sizeof(struct amdgpu_bo);
|
||||
|
||||
r = amdgpu_bo_create(adev, &bp, &vram_obj);
|
||||
if (r) {
|
||||
|
@ -823,15 +823,14 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_device *bdev,
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bdev);
|
||||
struct amdgpu_ttm_tt *gtt = (void *)ttm;
|
||||
int r;
|
||||
|
||||
int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY);
|
||||
enum dma_data_direction direction = write ?
|
||||
DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
|
||||
int r;
|
||||
|
||||
/* Allocate an SG array and squash pages into it */
|
||||
r = sg_alloc_table_from_pages(ttm->sg, ttm->pages, ttm->num_pages, 0,
|
||||
ttm->num_pages << PAGE_SHIFT,
|
||||
(u64)ttm->num_pages << PAGE_SHIFT,
|
||||
GFP_KERNEL);
|
||||
if (r)
|
||||
goto release_sg;
|
||||
@ -861,13 +860,12 @@ static void amdgpu_ttm_tt_unpin_userptr(struct ttm_device *bdev,
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bdev);
|
||||
struct amdgpu_ttm_tt *gtt = (void *)ttm;
|
||||
|
||||
int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY);
|
||||
enum dma_data_direction direction = write ?
|
||||
DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
|
||||
|
||||
/* double check that we don't free the table twice */
|
||||
if (!ttm->sg->sgl)
|
||||
if (!ttm->sg || !ttm->sg->sgl)
|
||||
return;
|
||||
|
||||
/* unmap the pages mapped to the device */
|
||||
@ -1087,13 +1085,13 @@ static void amdgpu_ttm_backend_unbind(struct ttm_device *bdev,
|
||||
struct amdgpu_ttm_tt *gtt = (void *)ttm;
|
||||
int r;
|
||||
|
||||
if (!gtt->bound)
|
||||
return;
|
||||
|
||||
/* if the pages have userptr pinning then clear that first */
|
||||
if (gtt->userptr)
|
||||
amdgpu_ttm_tt_unpin_userptr(bdev, ttm);
|
||||
|
||||
if (!gtt->bound)
|
||||
return;
|
||||
|
||||
if (gtt->offset == AMDGPU_BO_INVALID_OFFSET)
|
||||
return;
|
||||
|
||||
@ -1503,7 +1501,7 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo,
|
||||
memcpy(buf, &value, bytes);
|
||||
}
|
||||
} else {
|
||||
bytes = cursor.size & 0x3ull;
|
||||
bytes = cursor.size & ~0x3ULL;
|
||||
amdgpu_device_vram_access(adev, cursor.start,
|
||||
(uint32_t *)buf, bytes,
|
||||
write);
|
||||
|
@ -60,8 +60,9 @@ int amdgpu_umc_ras_late_init(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
/* ras init of specific umc version */
|
||||
if (adev->umc.funcs && adev->umc.funcs->err_cnt_init)
|
||||
adev->umc.funcs->err_cnt_init(adev);
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->err_cnt_init)
|
||||
adev->umc.ras_funcs->err_cnt_init(adev);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -95,12 +96,12 @@ int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev,
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
|
||||
kgd2kfd_set_sram_ecc_flag(adev->kfd.dev);
|
||||
if (adev->umc.funcs &&
|
||||
adev->umc.funcs->query_ras_error_count)
|
||||
adev->umc.funcs->query_ras_error_count(adev, ras_error_status);
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->query_ras_error_count)
|
||||
adev->umc.ras_funcs->query_ras_error_count(adev, ras_error_status);
|
||||
|
||||
if (adev->umc.funcs &&
|
||||
adev->umc.funcs->query_ras_error_address &&
|
||||
if (adev->umc.ras_funcs &&
|
||||
adev->umc.ras_funcs->query_ras_error_address &&
|
||||
adev->umc.max_ras_err_cnt_per_query) {
|
||||
err_data->err_addr =
|
||||
kcalloc(adev->umc.max_ras_err_cnt_per_query,
|
||||
@ -116,7 +117,7 @@ int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev,
|
||||
/* umc query_ras_error_address is also responsible for clearing
|
||||
* error status
|
||||
*/
|
||||
adev->umc.funcs->query_ras_error_address(adev, ras_error_status);
|
||||
adev->umc.ras_funcs->query_ras_error_address(adev, ras_error_status);
|
||||
}
|
||||
|
||||
/* only uncorrectable error needs gpu reset */
|
||||
|
@ -35,13 +35,17 @@
|
||||
#define LOOP_UMC_CH_INST(ch_inst) for ((ch_inst) = 0; (ch_inst) < adev->umc.channel_inst_num; (ch_inst)++)
|
||||
#define LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) LOOP_UMC_INST((umc_inst)) LOOP_UMC_CH_INST((ch_inst))
|
||||
|
||||
struct amdgpu_umc_funcs {
|
||||
struct amdgpu_umc_ras_funcs {
|
||||
void (*err_cnt_init)(struct amdgpu_device *adev);
|
||||
int (*ras_late_init)(struct amdgpu_device *adev);
|
||||
void (*ras_fini)(struct amdgpu_device *adev);
|
||||
void (*query_ras_error_count)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
void *ras_error_status);
|
||||
void (*query_ras_error_address)(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
};
|
||||
|
||||
struct amdgpu_umc_funcs {
|
||||
void (*init_registers)(struct amdgpu_device *adev);
|
||||
};
|
||||
|
||||
@ -59,6 +63,7 @@ struct amdgpu_umc {
|
||||
struct ras_common_if *ras_if;
|
||||
|
||||
const struct amdgpu_umc_funcs *funcs;
|
||||
const struct amdgpu_umc_ras_funcs *ras_funcs;
|
||||
};
|
||||
|
||||
int amdgpu_umc_ras_late_init(struct amdgpu_device *adev);
|
||||
|
@ -259,7 +259,7 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
|
||||
if ((adev->asic_type == CHIP_POLARIS10 ||
|
||||
adev->asic_type == CHIP_POLARIS11) &&
|
||||
(adev->uvd.fw_version < FW_1_66_16))
|
||||
DRM_ERROR("POLARIS10/11 UVD firmware version %hu.%hu is too old.\n",
|
||||
DRM_ERROR("POLARIS10/11 UVD firmware version %u.%u is too old.\n",
|
||||
version_major, version_minor);
|
||||
} else {
|
||||
unsigned int enc_major, enc_minor, dec_minor;
|
||||
|
@ -212,6 +212,7 @@ struct amdgpu_vcn_inst {
|
||||
void *saved_bo;
|
||||
struct amdgpu_ring ring_dec;
|
||||
struct amdgpu_ring ring_enc[AMDGPU_VCN_MAX_ENC_RINGS];
|
||||
atomic_t sched_score;
|
||||
struct amdgpu_irq_src irq;
|
||||
struct amdgpu_vcn_reg external;
|
||||
struct amdgpu_bo *dpg_sram_bo;
|
||||
|
@ -466,6 +466,8 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev)
|
||||
((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->vf2pf_update_interval_ms;
|
||||
adev->virt.gim_feature =
|
||||
((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->feature_flags.all;
|
||||
adev->virt.reg_access =
|
||||
((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->reg_access_flags.all;
|
||||
|
||||
break;
|
||||
default:
|
||||
@ -617,6 +619,14 @@ void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev)
|
||||
if (adev->virt.ras_init_done)
|
||||
amdgpu_virt_add_bad_page(adev, bp_block_offset, bp_block_size);
|
||||
}
|
||||
} else if (adev->bios != NULL) {
|
||||
adev->virt.fw_reserve.p_pf2vf =
|
||||
(struct amd_sriov_msg_pf2vf_info_header *)
|
||||
(adev->bios + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB << 10));
|
||||
|
||||
amdgpu_virt_read_pf2vf_data(adev);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (adev->virt.vf2pf_update_interval_ms != 0) {
|
||||
|
@ -104,6 +104,17 @@ enum AMDGIM_FEATURE_FLAG {
|
||||
AMDGIM_FEATURE_GIM_MM_BW_MGR = 0x8,
|
||||
/* PP ONE VF MODE in GIM */
|
||||
AMDGIM_FEATURE_PP_ONE_VF = (1 << 4),
|
||||
/* Indirect Reg Access enabled */
|
||||
AMDGIM_FEATURE_INDIRECT_REG_ACCESS = (1 << 5),
|
||||
};
|
||||
|
||||
enum AMDGIM_REG_ACCESS_FLAG {
|
||||
/* Use PSP to program IH_RB_CNTL */
|
||||
AMDGIM_FEATURE_IH_REG_PSP_EN = (1 << 0),
|
||||
/* Use RLC to program MMHUB regs */
|
||||
AMDGIM_FEATURE_MMHUB_REG_RLC_EN = (1 << 1),
|
||||
/* Use RLC to program GC regs */
|
||||
AMDGIM_FEATURE_GC_REG_RLC_EN = (1 << 2),
|
||||
};
|
||||
|
||||
struct amdgim_pf2vf_info_v1 {
|
||||
@ -217,6 +228,7 @@ struct amdgpu_virt {
|
||||
bool tdr_debug;
|
||||
struct amdgpu_virt_ras_err_handler_data *virt_eh_data;
|
||||
bool ras_init_done;
|
||||
uint32_t reg_access;
|
||||
|
||||
/* vf2pf message */
|
||||
struct delayed_work vf2pf_work;
|
||||
@ -238,6 +250,22 @@ struct amdgpu_virt {
|
||||
#define amdgpu_sriov_fullaccess(adev) \
|
||||
(amdgpu_sriov_vf((adev)) && !amdgpu_sriov_runtime((adev)))
|
||||
|
||||
#define amdgpu_sriov_reg_indirect_en(adev) \
|
||||
(amdgpu_sriov_vf((adev)) && \
|
||||
((adev)->virt.gim_feature & (AMDGIM_FEATURE_INDIRECT_REG_ACCESS)))
|
||||
|
||||
#define amdgpu_sriov_reg_indirect_ih(adev) \
|
||||
(amdgpu_sriov_vf((adev)) && \
|
||||
((adev)->virt.reg_access & (AMDGIM_FEATURE_IH_REG_PSP_EN)))
|
||||
|
||||
#define amdgpu_sriov_reg_indirect_mmhub(adev) \
|
||||
(amdgpu_sriov_vf((adev)) && \
|
||||
((adev)->virt.reg_access & (AMDGIM_FEATURE_MMHUB_REG_RLC_EN)))
|
||||
|
||||
#define amdgpu_sriov_reg_indirect_gc(adev) \
|
||||
(amdgpu_sriov_vf((adev)) && \
|
||||
((adev)->virt.reg_access & (AMDGIM_FEATURE_GC_REG_RLC_EN)))
|
||||
|
||||
#define amdgpu_passthrough(adev) \
|
||||
((adev)->virt.caps & AMDGPU_PASSTHROUGH_MODE)
|
||||
|
||||
|
@ -869,6 +869,7 @@ static void amdgpu_vm_bo_param(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
bp->domain = amdgpu_bo_get_preferred_pin_domain(adev, bp->domain);
|
||||
bp->flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
|
||||
AMDGPU_GEM_CREATE_CPU_GTT_USWC;
|
||||
bp->bo_ptr_size = sizeof(struct amdgpu_bo);
|
||||
if (vm->use_cpu_for_update)
|
||||
bp->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
|
||||
else if (!vm->root.base.bo || vm->root.base.bo->shadow)
|
||||
@ -2197,8 +2198,8 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
|
||||
uint64_t eaddr;
|
||||
|
||||
/* validate the parameters */
|
||||
if (saddr & AMDGPU_GPU_PAGE_MASK || offset & AMDGPU_GPU_PAGE_MASK ||
|
||||
size == 0 || size & AMDGPU_GPU_PAGE_MASK)
|
||||
if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK ||
|
||||
size == 0 || size & ~PAGE_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
/* make sure object fit at this offset */
|
||||
@ -2263,8 +2264,8 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
|
||||
int r;
|
||||
|
||||
/* validate the parameters */
|
||||
if (saddr & AMDGPU_GPU_PAGE_MASK || offset & AMDGPU_GPU_PAGE_MASK ||
|
||||
size == 0 || size & AMDGPU_GPU_PAGE_MASK)
|
||||
if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK ||
|
||||
size == 0 || size & ~PAGE_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
/* make sure object fit at this offset */
|
||||
@ -2409,7 +2410,7 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev,
|
||||
after->start = eaddr + 1;
|
||||
after->last = tmp->last;
|
||||
after->offset = tmp->offset;
|
||||
after->offset += after->start - tmp->start;
|
||||
after->offset += (after->start - tmp->start) << PAGE_SHIFT;
|
||||
after->flags = tmp->flags;
|
||||
after->bo_va = tmp->bo_va;
|
||||
list_add(&after->list, &tmp->bo_va->invalids);
|
||||
@ -3300,7 +3301,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
|
||||
struct amdgpu_bo *root;
|
||||
uint64_t value, flags;
|
||||
struct amdgpu_vm *vm;
|
||||
long r;
|
||||
int r;
|
||||
|
||||
spin_lock(&adev->vm_manager.pasid_lock);
|
||||
vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
|
||||
@ -3349,6 +3350,12 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
|
||||
value = 0;
|
||||
}
|
||||
|
||||
r = dma_resv_reserve_shared(root->tbo.base.resv, 1);
|
||||
if (r) {
|
||||
pr_debug("failed %d to reserve fence slot\n", r);
|
||||
goto error_unlock;
|
||||
}
|
||||
|
||||
r = amdgpu_vm_bo_update_mapping(adev, adev, vm, true, false, NULL, addr,
|
||||
addr, flags, value, NULL, NULL,
|
||||
NULL);
|
||||
@ -3360,7 +3367,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
|
||||
error_unlock:
|
||||
amdgpu_bo_unreserve(root);
|
||||
if (r < 0)
|
||||
DRM_ERROR("Can't handle page fault (%ld)\n", r);
|
||||
DRM_ERROR("Can't handle page fault (%d)\n", r);
|
||||
|
||||
error_unref:
|
||||
amdgpu_bo_unref(&root);
|
||||
|
@ -52,7 +52,7 @@ static ssize_t amdgpu_mem_info_vram_total_show(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%llu\n", adev->gmc.real_vram_size);
|
||||
return sysfs_emit(buf, "%llu\n", adev->gmc.real_vram_size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,7 +69,7 @@ static ssize_t amdgpu_mem_info_vis_vram_total_show(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%llu\n", adev->gmc.visible_vram_size);
|
||||
return sysfs_emit(buf, "%llu\n", adev->gmc.visible_vram_size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -87,8 +87,7 @@ static ssize_t amdgpu_mem_info_vram_used_show(struct device *dev,
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%llu\n",
|
||||
amdgpu_vram_mgr_usage(man));
|
||||
return sysfs_emit(buf, "%llu\n", amdgpu_vram_mgr_usage(man));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -106,8 +105,7 @@ static ssize_t amdgpu_mem_info_vis_vram_used_show(struct device *dev,
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
struct ttm_resource_manager *man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%llu\n",
|
||||
amdgpu_vram_mgr_vis_usage(man));
|
||||
return sysfs_emit(buf, "%llu\n", amdgpu_vram_mgr_vis_usage(man));
|
||||
}
|
||||
|
||||
static ssize_t amdgpu_mem_info_vram_vendor(struct device *dev,
|
||||
@ -119,27 +117,27 @@ static ssize_t amdgpu_mem_info_vram_vendor(struct device *dev,
|
||||
|
||||
switch (adev->gmc.vram_vendor) {
|
||||
case SAMSUNG:
|
||||
return snprintf(buf, PAGE_SIZE, "samsung\n");
|
||||
return sysfs_emit(buf, "samsung\n");
|
||||
case INFINEON:
|
||||
return snprintf(buf, PAGE_SIZE, "infineon\n");
|
||||
return sysfs_emit(buf, "infineon\n");
|
||||
case ELPIDA:
|
||||
return snprintf(buf, PAGE_SIZE, "elpida\n");
|
||||
return sysfs_emit(buf, "elpida\n");
|
||||
case ETRON:
|
||||
return snprintf(buf, PAGE_SIZE, "etron\n");
|
||||
return sysfs_emit(buf, "etron\n");
|
||||
case NANYA:
|
||||
return snprintf(buf, PAGE_SIZE, "nanya\n");
|
||||
return sysfs_emit(buf, "nanya\n");
|
||||
case HYNIX:
|
||||
return snprintf(buf, PAGE_SIZE, "hynix\n");
|
||||
return sysfs_emit(buf, "hynix\n");
|
||||
case MOSEL:
|
||||
return snprintf(buf, PAGE_SIZE, "mosel\n");
|
||||
return sysfs_emit(buf, "mosel\n");
|
||||
case WINBOND:
|
||||
return snprintf(buf, PAGE_SIZE, "winbond\n");
|
||||
return sysfs_emit(buf, "winbond\n");
|
||||
case ESMT:
|
||||
return snprintf(buf, PAGE_SIZE, "esmt\n");
|
||||
return sysfs_emit(buf, "esmt\n");
|
||||
case MICRON:
|
||||
return snprintf(buf, PAGE_SIZE, "micron\n");
|
||||
return sysfs_emit(buf, "micron\n");
|
||||
default:
|
||||
return snprintf(buf, PAGE_SIZE, "unknown\n");
|
||||
return sysfs_emit(buf, "unknown\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <linux/list.h>
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_xgmi.h"
|
||||
#include "amdgpu_smu.h"
|
||||
#include "amdgpu_ras.h"
|
||||
#include "soc15.h"
|
||||
#include "df/df_3_6_offset.h"
|
||||
@ -217,7 +216,7 @@ static ssize_t amdgpu_xgmi_show_device_id(struct device *dev,
|
||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct amdgpu_device *adev = drm_to_adev(ddev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%llu\n", adev->gmc.xgmi.node_id);
|
||||
return sysfs_emit(buf, "%llu\n", adev->gmc.xgmi.node_id);
|
||||
|
||||
}
|
||||
|
||||
@ -246,7 +245,7 @@ static ssize_t amdgpu_xgmi_show_error(struct device *dev,
|
||||
|
||||
adev->df.funcs->set_fica(adev, ficaa_pie_status_in, 0, 0);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%u\n", error_count);
|
||||
return sysfs_emit(buf, "%u\n", error_count);
|
||||
}
|
||||
|
||||
|
||||
@ -629,7 +628,7 @@ int amdgpu_xgmi_remove_device(struct amdgpu_device *adev)
|
||||
return psp_xgmi_terminate(&adev->psp);
|
||||
}
|
||||
|
||||
int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev)
|
||||
static int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev)
|
||||
{
|
||||
int r;
|
||||
struct ras_ih_if ih_info = {
|
||||
@ -643,7 +642,7 @@ int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev)
|
||||
adev->gmc.xgmi.num_physical_nodes == 0)
|
||||
return 0;
|
||||
|
||||
amdgpu_xgmi_reset_ras_error_count(adev);
|
||||
adev->gmc.xgmi.ras_funcs->reset_ras_error_count(adev);
|
||||
|
||||
if (!adev->gmc.xgmi.ras_if) {
|
||||
adev->gmc.xgmi.ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL);
|
||||
@ -665,7 +664,7 @@ int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev)
|
||||
return r;
|
||||
}
|
||||
|
||||
void amdgpu_xgmi_ras_fini(struct amdgpu_device *adev)
|
||||
static void amdgpu_xgmi_ras_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__XGMI_WAFL) &&
|
||||
adev->gmc.xgmi.ras_if) {
|
||||
@ -692,7 +691,7 @@ static void pcs_clear_status(struct amdgpu_device *adev, uint32_t pcs_status_reg
|
||||
WREG32_PCIE(pcs_status_reg, 0);
|
||||
}
|
||||
|
||||
void amdgpu_xgmi_reset_ras_error_count(struct amdgpu_device *adev)
|
||||
static void amdgpu_xgmi_reset_ras_error_count(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
@ -752,8 +751,8 @@ static int amdgpu_xgmi_query_pcs_error_status(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
static int amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
{
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
int i;
|
||||
@ -802,10 +801,17 @@ int amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
|
||||
break;
|
||||
}
|
||||
|
||||
amdgpu_xgmi_reset_ras_error_count(adev);
|
||||
adev->gmc.xgmi.ras_funcs->reset_ras_error_count(adev);
|
||||
|
||||
err_data->ue_count += ue_cnt;
|
||||
err_data->ce_count += ce_cnt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct amdgpu_xgmi_ras_funcs xgmi_ras_funcs = {
|
||||
.ras_late_init = amdgpu_xgmi_ras_late_init,
|
||||
.ras_fini = amdgpu_xgmi_ras_fini,
|
||||
.query_ras_error_count = amdgpu_xgmi_query_ras_error_count,
|
||||
.reset_ras_error_count = amdgpu_xgmi_reset_ras_error_count,
|
||||
};
|
||||
|
@ -50,6 +50,7 @@ struct amdgpu_pcs_ras_field {
|
||||
uint32_t pcs_err_shift;
|
||||
};
|
||||
|
||||
extern const struct amdgpu_xgmi_ras_funcs xgmi_ras_funcs;
|
||||
struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev);
|
||||
void amdgpu_put_xgmi_hive(struct amdgpu_hive_info *hive);
|
||||
int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev);
|
||||
@ -58,14 +59,8 @@ int amdgpu_xgmi_remove_device(struct amdgpu_device *adev);
|
||||
int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate);
|
||||
int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev,
|
||||
struct amdgpu_device *peer_adev);
|
||||
int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev);
|
||||
void amdgpu_xgmi_ras_fini(struct amdgpu_device *adev);
|
||||
uint64_t amdgpu_xgmi_get_relative_phy_addr(struct amdgpu_device *adev,
|
||||
uint64_t addr);
|
||||
int amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
void amdgpu_xgmi_reset_ras_error_count(struct amdgpu_device *adev);
|
||||
|
||||
static inline bool amdgpu_xgmi_same_hive(struct amdgpu_device *adev,
|
||||
struct amdgpu_device *bo_adev)
|
||||
{
|
||||
|
@ -90,11 +90,22 @@ union amd_sriov_msg_feature_flags {
|
||||
uint32_t host_flr_vramlost : 1;
|
||||
uint32_t mm_bw_management : 1;
|
||||
uint32_t pp_one_vf_mode : 1;
|
||||
uint32_t reserved : 27;
|
||||
uint32_t reg_indirect_acc : 1;
|
||||
uint32_t reserved : 26;
|
||||
} flags;
|
||||
uint32_t all;
|
||||
};
|
||||
|
||||
union amd_sriov_reg_access_flags {
|
||||
struct {
|
||||
uint32_t vf_reg_access_ih : 1;
|
||||
uint32_t vf_reg_access_mmhub : 1;
|
||||
uint32_t vf_reg_access_gc : 1;
|
||||
uint32_t reserved : 29;
|
||||
} flags;
|
||||
uint32_t all;
|
||||
};
|
||||
|
||||
union amd_sriov_msg_os_info {
|
||||
struct {
|
||||
uint32_t windows : 1;
|
||||
@ -149,8 +160,10 @@ struct amd_sriov_msg_pf2vf_info {
|
||||
/* identification in ROCm SMI */
|
||||
uint64_t uuid;
|
||||
uint32_t fcn_idx;
|
||||
/* flags which indicate the register access method VF should use */
|
||||
union amd_sriov_reg_access_flags reg_access_flags;
|
||||
/* reserved */
|
||||
uint32_t reserved[256-26];
|
||||
uint32_t reserved[256-27];
|
||||
};
|
||||
|
||||
struct amd_sriov_msg_vf2pf_info_header {
|
||||
|
@ -984,10 +984,9 @@ static int cik_sdma_sw_init(void *handle)
|
||||
sprintf(ring->name, "sdma%d", i);
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->sdma.trap_irq,
|
||||
(i == 0) ?
|
||||
AMDGPU_SDMA_IRQ_INSTANCE0 :
|
||||
(i == 0) ? AMDGPU_SDMA_IRQ_INSTANCE0 :
|
||||
AMDGPU_SDMA_IRQ_INSTANCE1,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -2896,6 +2896,11 @@ static int dce_v10_0_hw_fini(void *handle)
|
||||
static int dce_v10_0_suspend(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int r;
|
||||
|
||||
r = amdgpu_display_suspend_helper(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
adev->mode_info.bl_level =
|
||||
amdgpu_atombios_encoder_get_backlight_level_from_reg(adev);
|
||||
@ -2920,8 +2925,10 @@ static int dce_v10_0_resume(void *handle)
|
||||
amdgpu_display_backlight_set_level(adev, adev->mode_info.bl_encoder,
|
||||
bl_level);
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
return amdgpu_display_resume_helper(adev);
|
||||
}
|
||||
|
||||
static bool dce_v10_0_is_idle(void *handle)
|
||||
|
@ -3026,6 +3026,11 @@ static int dce_v11_0_hw_fini(void *handle)
|
||||
static int dce_v11_0_suspend(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int r;
|
||||
|
||||
r = amdgpu_display_suspend_helper(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
adev->mode_info.bl_level =
|
||||
amdgpu_atombios_encoder_get_backlight_level_from_reg(adev);
|
||||
@ -3050,8 +3055,10 @@ static int dce_v11_0_resume(void *handle)
|
||||
amdgpu_display_backlight_set_level(adev, adev->mode_info.bl_encoder,
|
||||
bl_level);
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
return amdgpu_display_resume_helper(adev);
|
||||
}
|
||||
|
||||
static bool dce_v11_0_is_idle(void *handle)
|
||||
|
@ -2769,7 +2769,11 @@ static int dce_v6_0_hw_fini(void *handle)
|
||||
static int dce_v6_0_suspend(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int r;
|
||||
|
||||
r = amdgpu_display_suspend_helper(adev);
|
||||
if (r)
|
||||
return r;
|
||||
adev->mode_info.bl_level =
|
||||
amdgpu_atombios_encoder_get_backlight_level_from_reg(adev);
|
||||
|
||||
@ -2793,8 +2797,10 @@ static int dce_v6_0_resume(void *handle)
|
||||
amdgpu_display_backlight_set_level(adev, adev->mode_info.bl_encoder,
|
||||
bl_level);
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
return amdgpu_display_resume_helper(adev);
|
||||
}
|
||||
|
||||
static bool dce_v6_0_is_idle(void *handle)
|
||||
|
@ -2795,6 +2795,11 @@ static int dce_v8_0_hw_fini(void *handle)
|
||||
static int dce_v8_0_suspend(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int r;
|
||||
|
||||
r = amdgpu_display_suspend_helper(adev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
adev->mode_info.bl_level =
|
||||
amdgpu_atombios_encoder_get_backlight_level_from_reg(adev);
|
||||
@ -2819,8 +2824,10 @@ static int dce_v8_0_resume(void *handle)
|
||||
amdgpu_display_backlight_set_level(adev, adev->mode_info.bl_encoder,
|
||||
bl_level);
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
return amdgpu_display_resume_helper(adev);
|
||||
}
|
||||
|
||||
static bool dce_v8_0_is_idle(void *handle)
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "dce_v11_0.h"
|
||||
#include "dce_virtual.h"
|
||||
#include "ivsrcid/ivsrcid_vislands30.h"
|
||||
#include "amdgpu_display.h"
|
||||
|
||||
#define DCE_VIRTUAL_VBLANK_PERIOD 16666666
|
||||
|
||||
@ -491,12 +492,24 @@ static int dce_virtual_hw_fini(void *handle)
|
||||
|
||||
static int dce_virtual_suspend(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int r;
|
||||
|
||||
r = amdgpu_display_suspend_helper(adev);
|
||||
if (r)
|
||||
return r;
|
||||
return dce_virtual_hw_fini(handle);
|
||||
}
|
||||
|
||||
static int dce_virtual_resume(void *handle)
|
||||
{
|
||||
return dce_virtual_hw_init(handle);
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
int r;
|
||||
|
||||
r = dce_virtual_hw_init(handle);
|
||||
if (r)
|
||||
return r;
|
||||
return amdgpu_display_resume_helper(adev);
|
||||
}
|
||||
|
||||
static bool dce_virtual_is_idle(void *handle)
|
||||
|
@ -205,7 +205,7 @@ static ssize_t df_v3_6_get_df_cntr_avail(struct device *dev,
|
||||
count++;
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%i\n", count);
|
||||
return sysfs_emit(buf, "%i\n", count);
|
||||
}
|
||||
|
||||
/* device attr for available perfmon counters */
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_gfx.h"
|
||||
#include "amdgpu_psp.h"
|
||||
#include "amdgpu_smu.h"
|
||||
#include "nv.h"
|
||||
#include "nvd.h"
|
||||
|
||||
@ -174,6 +173,11 @@
|
||||
#define mmGC_THROTTLE_CTRL_Sienna_Cichlid 0x2030
|
||||
#define mmGC_THROTTLE_CTRL_Sienna_Cichlid_BASE_IDX 0
|
||||
|
||||
#define GFX_RLCG_GC_WRITE_OLD (0x8 << 28)
|
||||
#define GFX_RLCG_GC_WRITE (0x0 << 28)
|
||||
#define GFX_RLCG_GC_READ (0x1 << 28)
|
||||
#define GFX_RLCG_MMHUB_WRITE (0x2 << 28)
|
||||
|
||||
MODULE_FIRMWARE("amdgpu/navi10_ce.bin");
|
||||
MODULE_FIRMWARE("amdgpu/navi10_pfp.bin");
|
||||
MODULE_FIRMWARE("amdgpu/navi10_me.bin");
|
||||
@ -1419,38 +1423,127 @@ static const struct soc15_reg_golden golden_settings_gc_10_1_2[] =
|
||||
SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffffffff, 0x00800000)
|
||||
};
|
||||
|
||||
static void gfx_v10_rlcg_wreg(struct amdgpu_device *adev, u32 offset, u32 v)
|
||||
static bool gfx_v10_is_rlcg_rw(struct amdgpu_device *adev, u32 offset, uint32_t *flag, bool write)
|
||||
{
|
||||
/* always programed by rlcg, only for gc */
|
||||
if (offset == SOC15_REG_OFFSET(GC, 0, mmRLC_CSIB_ADDR_HI) ||
|
||||
offset == SOC15_REG_OFFSET(GC, 0, mmRLC_CSIB_ADDR_LO) ||
|
||||
offset == SOC15_REG_OFFSET(GC, 0, mmRLC_CSIB_LENGTH) ||
|
||||
offset == SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_CNTL) ||
|
||||
offset == SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_INDEX) ||
|
||||
offset == SOC15_REG_OFFSET(GC, 0, mmCP_ME_CNTL)) {
|
||||
if (!amdgpu_sriov_reg_indirect_gc(adev))
|
||||
*flag = GFX_RLCG_GC_WRITE_OLD;
|
||||
else
|
||||
*flag = write ? GFX_RLCG_GC_WRITE : GFX_RLCG_GC_READ;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* currently support gc read/write, mmhub write */
|
||||
if (offset >= SOC15_REG_OFFSET(GC, 0, mmSDMA0_DEC_START) &&
|
||||
offset <= SOC15_REG_OFFSET(GC, 0, mmRLC_GTS_OFFSET_MSB)) {
|
||||
if (amdgpu_sriov_reg_indirect_gc(adev))
|
||||
*flag = write ? GFX_RLCG_GC_WRITE : GFX_RLCG_GC_READ;
|
||||
else
|
||||
return false;
|
||||
} else {
|
||||
if (amdgpu_sriov_reg_indirect_mmhub(adev))
|
||||
*flag = GFX_RLCG_MMHUB_WRITE;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static u32 gfx_v10_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32_t flag)
|
||||
{
|
||||
static void *scratch_reg0;
|
||||
static void *scratch_reg1;
|
||||
static void *scratch_reg2;
|
||||
static void *scratch_reg3;
|
||||
static void *spare_int;
|
||||
static uint32_t grbm_cntl;
|
||||
static uint32_t grbm_idx;
|
||||
uint32_t i = 0;
|
||||
uint32_t retries = 50000;
|
||||
u32 ret = 0;
|
||||
|
||||
scratch_reg0 = adev->rmmio + (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG0_BASE_IDX] + mmSCRATCH_REG0)*4;
|
||||
scratch_reg1 = adev->rmmio + (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG1_BASE_IDX] + mmSCRATCH_REG1)*4;
|
||||
spare_int = adev->rmmio + (adev->reg_offset[GC_HWIP][0][mmRLC_SPARE_INT_BASE_IDX] + mmRLC_SPARE_INT)*4;
|
||||
scratch_reg0 = adev->rmmio +
|
||||
(adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG0_BASE_IDX] + mmSCRATCH_REG0) * 4;
|
||||
scratch_reg1 = adev->rmmio +
|
||||
(adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG1_BASE_IDX] + mmSCRATCH_REG1) * 4;
|
||||
scratch_reg2 = adev->rmmio +
|
||||
(adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG0_BASE_IDX] + mmSCRATCH_REG2) * 4;
|
||||
scratch_reg3 = adev->rmmio +
|
||||
(adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG1_BASE_IDX] + mmSCRATCH_REG3) * 4;
|
||||
spare_int = adev->rmmio +
|
||||
(adev->reg_offset[GC_HWIP][0][mmRLC_SPARE_INT_BASE_IDX] + mmRLC_SPARE_INT) * 4;
|
||||
|
||||
grbm_cntl = adev->reg_offset[GC_HWIP][0][mmGRBM_GFX_CNTL_BASE_IDX] + mmGRBM_GFX_CNTL;
|
||||
grbm_idx = adev->reg_offset[GC_HWIP][0][mmGRBM_GFX_INDEX_BASE_IDX] + mmGRBM_GFX_INDEX;
|
||||
|
||||
if (offset == grbm_cntl || offset == grbm_idx) {
|
||||
if (offset == grbm_cntl)
|
||||
writel(v, scratch_reg2);
|
||||
else if (offset == grbm_idx)
|
||||
writel(v, scratch_reg3);
|
||||
|
||||
writel(v, ((void __iomem *)adev->rmmio) + (offset * 4));
|
||||
} else {
|
||||
writel(v, scratch_reg0);
|
||||
writel(offset | flag, scratch_reg1);
|
||||
writel(1, spare_int);
|
||||
for (i = 0; i < retries; i++) {
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl(scratch_reg1);
|
||||
if (!(tmp & flag))
|
||||
break;
|
||||
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
if (i >= retries)
|
||||
pr_err("timeout: rlcg program reg:0x%05x failed !\n", offset);
|
||||
}
|
||||
|
||||
ret = readl(scratch_reg0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void gfx_v10_rlcg_wreg(struct amdgpu_device *adev, u32 offset, u32 value, u32 flag)
|
||||
{
|
||||
uint32_t rlcg_flag;
|
||||
|
||||
if (amdgpu_sriov_fullaccess(adev) &&
|
||||
gfx_v10_is_rlcg_rw(adev, offset, &rlcg_flag, 1)) {
|
||||
gfx_v10_rlcg_rw(adev, offset, value, rlcg_flag);
|
||||
|
||||
if (amdgpu_sriov_runtime(adev)) {
|
||||
pr_err("shouldn't call rlcg write register during runtime\n");
|
||||
return;
|
||||
}
|
||||
if (flag & AMDGPU_REGS_NO_KIQ)
|
||||
WREG32_NO_KIQ(offset, value);
|
||||
else
|
||||
WREG32(offset, value);
|
||||
}
|
||||
|
||||
writel(v, scratch_reg0);
|
||||
writel(offset | 0x80000000, scratch_reg1);
|
||||
writel(1, spare_int);
|
||||
for (i = 0; i < retries; i++) {
|
||||
u32 tmp;
|
||||
static u32 gfx_v10_rlcg_rreg(struct amdgpu_device *adev, u32 offset, u32 flag)
|
||||
{
|
||||
uint32_t rlcg_flag;
|
||||
|
||||
tmp = readl(scratch_reg1);
|
||||
if (!(tmp & 0x80000000))
|
||||
break;
|
||||
if (amdgpu_sriov_fullaccess(adev) &&
|
||||
gfx_v10_is_rlcg_rw(adev, offset, &rlcg_flag, 0))
|
||||
return gfx_v10_rlcg_rw(adev, offset, 0, rlcg_flag);
|
||||
|
||||
udelay(10);
|
||||
}
|
||||
if (flag & AMDGPU_REGS_NO_KIQ)
|
||||
return RREG32_NO_KIQ(offset);
|
||||
else
|
||||
return RREG32(offset);
|
||||
|
||||
if (i >= retries)
|
||||
pr_err("timeout: rlcg program reg:0x%05x failed !\n", offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct soc15_reg_golden golden_settings_gc_10_1_nv14[] =
|
||||
@ -4459,9 +4552,8 @@ static int gfx_v10_0_gfx_ring_init(struct amdgpu_device *adev, int ring_id,
|
||||
sprintf(ring->name, "gfx_%d.%d.%d", ring->me, ring->pipe, ring->queue);
|
||||
|
||||
irq_type = AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP + ring->pipe;
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->gfx.eop_irq, irq_type,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq, irq_type,
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
return 0;
|
||||
@ -4495,8 +4587,8 @@ static int gfx_v10_0_compute_ring_init(struct amdgpu_device *adev, int ring_id,
|
||||
hw_prio = amdgpu_gfx_is_high_priority_compute_queue(adev, ring) ?
|
||||
AMDGPU_GFX_PIPE_PRIO_HIGH : AMDGPU_GFX_PIPE_PRIO_NORMAL;
|
||||
/* type-2 packets are deprecated on MEC, use type-3 instead */
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->gfx.eop_irq, irq_type, hw_prio);
|
||||
r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq, irq_type,
|
||||
hw_prio, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@ -7172,16 +7264,10 @@ static int gfx_v10_0_hw_init(void *handle)
|
||||
* loaded firstly, so in direct type, it has to load smc ucode
|
||||
* here before rlc.
|
||||
*/
|
||||
if (adev->smu.ppt_funcs != NULL && !(adev->flags & AMD_IS_APU)) {
|
||||
r = smu_load_microcode(&adev->smu);
|
||||
if (!(adev->flags & AMD_IS_APU)) {
|
||||
r = amdgpu_pm_load_smu_firmware(adev, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = smu_check_fw_status(&adev->smu);
|
||||
if (r) {
|
||||
pr_err("SMC firmware status is not correct\n");
|
||||
return r;
|
||||
}
|
||||
}
|
||||
gfx_v10_0_disable_gpa_mode(adev);
|
||||
}
|
||||
@ -7892,6 +7978,7 @@ static const struct amdgpu_rlc_funcs gfx_v10_0_rlc_funcs_sriov = {
|
||||
.start = gfx_v10_0_rlc_start,
|
||||
.update_spm_vmid = gfx_v10_0_update_spm_vmid,
|
||||
.rlcg_wreg = gfx_v10_rlcg_wreg,
|
||||
.rlcg_rreg = gfx_v10_rlcg_rreg,
|
||||
.is_rlcg_access_range = gfx_v10_0_is_rlcg_access_range,
|
||||
};
|
||||
|
||||
|
@ -3114,7 +3114,7 @@ static int gfx_v6_0_sw_init(void *handle)
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->gfx.eop_irq,
|
||||
AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
@ -3137,7 +3137,7 @@ static int gfx_v6_0_sw_init(void *handle)
|
||||
irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe;
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->gfx.eop_irq, irq_type,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -1877,7 +1877,7 @@ static void gfx_v7_0_init_compute_vmid(struct amdgpu_device *adev)
|
||||
mutex_unlock(&adev->srbm_mutex);
|
||||
|
||||
/* Initialize all compute VMIDs to have no GDS, GWS, or OA
|
||||
acccess. These should be enabled by FW for target VMIDs. */
|
||||
access. These should be enabled by FW for target VMIDs. */
|
||||
for (i = adev->vm_manager.first_kfd_vmid; i < AMDGPU_NUM_VMID; i++) {
|
||||
WREG32(amdgpu_gds_reg_offset[i].mem_base, 0);
|
||||
WREG32(amdgpu_gds_reg_offset[i].mem_size, 0);
|
||||
@ -2058,7 +2058,7 @@ static void gfx_v7_0_constants_init(struct amdgpu_device *adev)
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Set up the number and offset of the CP scratch registers.
|
||||
* NOTE: use of CP scratch registers is a legacy inferface and
|
||||
* NOTE: use of CP scratch registers is a legacy interface and
|
||||
* is not used by default on newer asics (r6xx+). On newer asics,
|
||||
* memory buffers are used for fences rather than scratch regs.
|
||||
*/
|
||||
@ -2172,7 +2172,7 @@ static void gfx_v7_0_ring_emit_vgt_flush(struct amdgpu_ring *ring)
|
||||
* @seq: sequence number
|
||||
* @flags: fence related flags
|
||||
*
|
||||
* Emits a fence sequnce number on the gfx ring and flushes
|
||||
* Emits a fence sequence number on the gfx ring and flushes
|
||||
* GPU caches.
|
||||
*/
|
||||
static void gfx_v7_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr,
|
||||
@ -2215,7 +2215,7 @@ static void gfx_v7_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr,
|
||||
* @seq: sequence number
|
||||
* @flags: fence related flags
|
||||
*
|
||||
* Emits a fence sequnce number on the compute ring and flushes
|
||||
* Emits a fence sequence number on the compute ring and flushes
|
||||
* GPU caches.
|
||||
*/
|
||||
static void gfx_v7_0_ring_emit_fence_compute(struct amdgpu_ring *ring,
|
||||
@ -2245,14 +2245,14 @@ static void gfx_v7_0_ring_emit_fence_compute(struct amdgpu_ring *ring,
|
||||
* gfx_v7_0_ring_emit_ib - emit an IB (Indirect Buffer) on the ring
|
||||
*
|
||||
* @ring: amdgpu_ring structure holding ring information
|
||||
* @job: job to retrive vmid from
|
||||
* @job: job to retrieve vmid from
|
||||
* @ib: amdgpu indirect buffer object
|
||||
* @flags: options (AMDGPU_HAVE_CTX_SWITCH)
|
||||
*
|
||||
* Emits an DE (drawing engine) or CE (constant engine) IB
|
||||
* on the gfx ring. IBs are usually generated by userspace
|
||||
* acceleration drivers and submitted to the kernel for
|
||||
* sheduling on the ring. This function schedules the IB
|
||||
* scheduling on the ring. This function schedules the IB
|
||||
* on the gfx ring for execution by the GPU.
|
||||
*/
|
||||
static void gfx_v7_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
|
||||
@ -2402,7 +2402,7 @@ err1:
|
||||
|
||||
/*
|
||||
* CP.
|
||||
* On CIK, gfx and compute now have independant command processors.
|
||||
* On CIK, gfx and compute now have independent command processors.
|
||||
*
|
||||
* GFX
|
||||
* Gfx consists of a single ring and can process both gfx jobs and
|
||||
@ -2630,7 +2630,7 @@ static int gfx_v7_0_cp_gfx_resume(struct amdgpu_device *adev)
|
||||
ring->wptr = 0;
|
||||
WREG32(mmCP_RB0_WPTR, lower_32_bits(ring->wptr));
|
||||
|
||||
/* set the wb address wether it's enabled or not */
|
||||
/* set the wb address whether it's enabled or not */
|
||||
rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
|
||||
WREG32(mmCP_RB0_RPTR_ADDR, lower_32_bits(rptr_addr));
|
||||
WREG32(mmCP_RB0_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
|
||||
@ -2985,7 +2985,7 @@ static void gfx_v7_0_mqd_init(struct amdgpu_device *adev,
|
||||
mqd->cp_hqd_pq_wptr_poll_addr_lo = wb_gpu_addr & 0xfffffffc;
|
||||
mqd->cp_hqd_pq_wptr_poll_addr_hi = upper_32_bits(wb_gpu_addr) & 0xffff;
|
||||
|
||||
/* set the wb address wether it's enabled or not */
|
||||
/* set the wb address whether it's enabled or not */
|
||||
wb_gpu_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
|
||||
mqd->cp_hqd_pq_rptr_report_addr_lo = wb_gpu_addr & 0xfffffffc;
|
||||
mqd->cp_hqd_pq_rptr_report_addr_hi =
|
||||
@ -3198,7 +3198,7 @@ static int gfx_v7_0_cp_resume(struct amdgpu_device *adev)
|
||||
/**
|
||||
* gfx_v7_0_ring_emit_vm_flush - cik vm flush using the CP
|
||||
*
|
||||
* @ring: the ring to emmit the commands to
|
||||
* @ring: the ring to emit the commands to
|
||||
*
|
||||
* Sync the command pipeline with the PFP. E.g. wait for everything
|
||||
* to be completed.
|
||||
@ -3220,7 +3220,7 @@ static void gfx_v7_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
|
||||
amdgpu_ring_write(ring, 4); /* poll interval */
|
||||
|
||||
if (usepfp) {
|
||||
/* synce CE with ME to prevent CE fetch CEIB before context switch done */
|
||||
/* sync CE with ME to prevent CE fetch CEIB before context switch done */
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
|
||||
amdgpu_ring_write(ring, 0);
|
||||
amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
|
||||
@ -4438,7 +4438,7 @@ static int gfx_v7_0_compute_ring_init(struct amdgpu_device *adev, int ring_id,
|
||||
/* type-2 packets are deprecated on MEC, use type-3 instead */
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->gfx.eop_irq, irq_type,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@ -4512,7 +4512,7 @@ static int gfx_v7_0_sw_init(void *handle)
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->gfx.eop_irq,
|
||||
AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -1927,8 +1927,8 @@ static int gfx_v8_0_compute_ring_init(struct amdgpu_device *adev, int ring_id,
|
||||
hw_prio = amdgpu_gfx_is_high_priority_compute_queue(adev, ring) ?
|
||||
AMDGPU_GFX_PIPE_PRIO_HIGH : AMDGPU_RING_PRIO_DEFAULT;
|
||||
/* type-2 packets are deprecated on MEC, use type-3 instead */
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->gfx.eop_irq, irq_type, hw_prio);
|
||||
r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq, irq_type,
|
||||
hw_prio, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@ -2033,7 +2033,7 @@ static int gfx_v8_0_sw_init(void *handle)
|
||||
|
||||
r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq,
|
||||
AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -734,7 +734,7 @@ static const u32 GFX_RLC_SRM_INDEX_CNTL_DATA_OFFSETS[] =
|
||||
mmRLC_SRM_INDEX_CNTL_DATA_7 - mmRLC_SRM_INDEX_CNTL_DATA_0,
|
||||
};
|
||||
|
||||
static void gfx_v9_0_rlcg_wreg(struct amdgpu_device *adev, u32 offset, u32 v)
|
||||
static void gfx_v9_0_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 flag)
|
||||
{
|
||||
static void *scratch_reg0;
|
||||
static void *scratch_reg1;
|
||||
@ -787,6 +787,20 @@ static void gfx_v9_0_rlcg_wreg(struct amdgpu_device *adev, u32 offset, u32 v)
|
||||
|
||||
}
|
||||
|
||||
static void gfx_v9_0_rlcg_wreg(struct amdgpu_device *adev, u32 offset, u32 v, u32 flag)
|
||||
{
|
||||
if (amdgpu_sriov_fullaccess(adev)) {
|
||||
gfx_v9_0_rlcg_rw(adev, offset, v, flag);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (flag & AMDGPU_REGS_NO_KIQ)
|
||||
WREG32_NO_KIQ(offset, v);
|
||||
else
|
||||
WREG32(offset, v);
|
||||
}
|
||||
|
||||
#define VEGA10_GB_ADDR_CONFIG_GOLDEN 0x2a114042
|
||||
#define VEGA12_GB_ADDR_CONFIG_GOLDEN 0x24104041
|
||||
#define RAVEN_GB_ADDR_CONFIG_GOLDEN 0x24000042
|
||||
@ -2089,45 +2103,22 @@ static void gfx_v9_0_select_me_pipe_q(struct amdgpu_device *adev,
|
||||
}
|
||||
|
||||
static const struct amdgpu_gfx_funcs gfx_v9_0_gfx_funcs = {
|
||||
.get_gpu_clock_counter = &gfx_v9_0_get_gpu_clock_counter,
|
||||
.select_se_sh = &gfx_v9_0_select_se_sh,
|
||||
.read_wave_data = &gfx_v9_0_read_wave_data,
|
||||
.read_wave_sgprs = &gfx_v9_0_read_wave_sgprs,
|
||||
.read_wave_vgprs = &gfx_v9_0_read_wave_vgprs,
|
||||
.select_me_pipe_q = &gfx_v9_0_select_me_pipe_q,
|
||||
.get_gpu_clock_counter = &gfx_v9_0_get_gpu_clock_counter,
|
||||
.select_se_sh = &gfx_v9_0_select_se_sh,
|
||||
.read_wave_data = &gfx_v9_0_read_wave_data,
|
||||
.read_wave_sgprs = &gfx_v9_0_read_wave_sgprs,
|
||||
.read_wave_vgprs = &gfx_v9_0_read_wave_vgprs,
|
||||
.select_me_pipe_q = &gfx_v9_0_select_me_pipe_q,
|
||||
};
|
||||
|
||||
static const struct amdgpu_gfx_ras_funcs gfx_v9_0_ras_funcs = {
|
||||
.ras_late_init = amdgpu_gfx_ras_late_init,
|
||||
.ras_fini = amdgpu_gfx_ras_fini,
|
||||
.ras_error_inject = &gfx_v9_0_ras_error_inject,
|
||||
.query_ras_error_count = &gfx_v9_0_query_ras_error_count,
|
||||
.reset_ras_error_count = &gfx_v9_0_reset_ras_error_count,
|
||||
};
|
||||
|
||||
static const struct amdgpu_gfx_funcs gfx_v9_4_gfx_funcs = {
|
||||
.get_gpu_clock_counter = &gfx_v9_0_get_gpu_clock_counter,
|
||||
.select_se_sh = &gfx_v9_0_select_se_sh,
|
||||
.read_wave_data = &gfx_v9_0_read_wave_data,
|
||||
.read_wave_sgprs = &gfx_v9_0_read_wave_sgprs,
|
||||
.read_wave_vgprs = &gfx_v9_0_read_wave_vgprs,
|
||||
.select_me_pipe_q = &gfx_v9_0_select_me_pipe_q,
|
||||
.ras_error_inject = &gfx_v9_4_ras_error_inject,
|
||||
.query_ras_error_count = &gfx_v9_4_query_ras_error_count,
|
||||
.reset_ras_error_count = &gfx_v9_4_reset_ras_error_count,
|
||||
.query_ras_error_status = &gfx_v9_4_query_ras_error_status,
|
||||
};
|
||||
|
||||
static const struct amdgpu_gfx_funcs gfx_v9_4_2_gfx_funcs = {
|
||||
.get_gpu_clock_counter = &gfx_v9_0_get_gpu_clock_counter,
|
||||
.select_se_sh = &gfx_v9_0_select_se_sh,
|
||||
.read_wave_data = &gfx_v9_0_read_wave_data,
|
||||
.read_wave_sgprs = &gfx_v9_0_read_wave_sgprs,
|
||||
.read_wave_vgprs = &gfx_v9_0_read_wave_vgprs,
|
||||
.select_me_pipe_q = &gfx_v9_0_select_me_pipe_q,
|
||||
.ras_error_inject = &gfx_v9_4_2_ras_error_inject,
|
||||
.query_ras_error_count = &gfx_v9_4_2_query_ras_error_count,
|
||||
.reset_ras_error_count = &gfx_v9_4_2_reset_ras_error_count,
|
||||
.query_ras_error_status = &gfx_v9_4_2_query_ras_error_status,
|
||||
.reset_ras_error_status = &gfx_v9_4_2_reset_ras_error_status,
|
||||
.enable_watchdog_timer = &gfx_v9_4_2_enable_watchdog_timer,
|
||||
};
|
||||
|
||||
static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
|
||||
{
|
||||
u32 gb_addr_config;
|
||||
@ -2154,6 +2145,7 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
|
||||
DRM_INFO("fix gfx.config for vega12\n");
|
||||
break;
|
||||
case CHIP_VEGA20:
|
||||
adev->gfx.ras_funcs = &gfx_v9_0_ras_funcs;
|
||||
adev->gfx.config.max_hw_contexts = 8;
|
||||
adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
|
||||
adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
|
||||
@ -2179,7 +2171,7 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
|
||||
gb_addr_config = RAVEN_GB_ADDR_CONFIG_GOLDEN;
|
||||
break;
|
||||
case CHIP_ARCTURUS:
|
||||
adev->gfx.funcs = &gfx_v9_4_gfx_funcs;
|
||||
adev->gfx.ras_funcs = &gfx_v9_4_ras_funcs;
|
||||
adev->gfx.config.max_hw_contexts = 8;
|
||||
adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
|
||||
adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
|
||||
@ -2200,7 +2192,7 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
|
||||
gb_addr_config |= 0x22010042;
|
||||
break;
|
||||
case CHIP_ALDEBARAN:
|
||||
adev->gfx.funcs = &gfx_v9_4_2_gfx_funcs;
|
||||
adev->gfx.ras_funcs = &gfx_v9_4_2_ras_funcs;
|
||||
adev->gfx.config.max_hw_contexts = 8;
|
||||
adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
|
||||
adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
|
||||
@ -2286,8 +2278,8 @@ static int gfx_v9_0_compute_ring_init(struct amdgpu_device *adev, int ring_id,
|
||||
hw_prio = amdgpu_gfx_is_high_priority_compute_queue(adev, ring) ?
|
||||
AMDGPU_GFX_PIPE_PRIO_HIGH : AMDGPU_GFX_PIPE_PRIO_NORMAL;
|
||||
/* type-2 packets are deprecated on MEC, use type-3 instead */
|
||||
return amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->gfx.eop_irq, irq_type, hw_prio);
|
||||
return amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq, irq_type,
|
||||
hw_prio, NULL);
|
||||
}
|
||||
|
||||
static int gfx_v9_0_sw_init(void *handle)
|
||||
@ -2376,10 +2368,9 @@ static int gfx_v9_0_sw_init(void *handle)
|
||||
sprintf(ring->name, "gfx_%d", i);
|
||||
ring->use_doorbell = true;
|
||||
ring->doorbell_index = adev->doorbell_index.gfx_ring0 << 1;
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->gfx.eop_irq,
|
||||
r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq,
|
||||
AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
@ -2434,7 +2425,9 @@ static int gfx_v9_0_sw_fini(void *handle)
|
||||
int i;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_gfx_ras_fini(adev);
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->ras_fini)
|
||||
adev->gfx.ras_funcs->ras_fini(adev);
|
||||
|
||||
for (i = 0; i < adev->gfx.num_gfx_rings; i++)
|
||||
amdgpu_ring_fini(&adev->gfx.gfx_ring[i]);
|
||||
@ -4025,8 +4018,14 @@ static int gfx_v9_0_hw_fini(void *handle)
|
||||
}
|
||||
|
||||
gfx_v9_0_cp_enable(adev, false);
|
||||
adev->gfx.rlc.funcs->stop(adev);
|
||||
|
||||
/* Skip suspend with A+A reset */
|
||||
if (adev->gmc.xgmi.connected_to_cpu && amdgpu_in_reset(adev)) {
|
||||
dev_dbg(adev->dev, "Device in reset. Skipping RLC halt\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
adev->gfx.rlc.funcs->stop(adev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4747,12 +4746,16 @@ static int gfx_v9_0_ecc_late_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = amdgpu_gfx_ras_late_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->ras_late_init) {
|
||||
r = adev->gfx.ras_funcs->ras_late_init(adev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (adev->gfx.funcs->enable_watchdog_timer)
|
||||
adev->gfx.funcs->enable_watchdog_timer(adev);
|
||||
if (adev->gfx.ras_funcs &&
|
||||
adev->gfx.ras_funcs->enable_watchdog_timer)
|
||||
adev->gfx.ras_funcs->enable_watchdog_timer(adev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -863,8 +863,8 @@ static int gfx_v9_4_ras_error_count(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gfx_v9_4_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
static int gfx_v9_4_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
{
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
uint32_t sec_count = 0, ded_count = 0;
|
||||
@ -906,7 +906,7 @@ int gfx_v9_4_query_ras_error_count(struct amdgpu_device *adev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gfx_v9_4_reset_ras_error_count(struct amdgpu_device *adev)
|
||||
static void gfx_v9_4_reset_ras_error_count(struct amdgpu_device *adev)
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
@ -971,7 +971,8 @@ void gfx_v9_4_reset_ras_error_count(struct amdgpu_device *adev)
|
||||
WREG32_SOC15(GC, 0, mmATC_L2_CACHE_4K_DSM_INDEX, 255);
|
||||
}
|
||||
|
||||
int gfx_v9_4_ras_error_inject(struct amdgpu_device *adev, void *inject_if)
|
||||
static int gfx_v9_4_ras_error_inject(struct amdgpu_device *adev,
|
||||
void *inject_if)
|
||||
{
|
||||
struct ras_inject_if *info = (struct ras_inject_if *)inject_if;
|
||||
int ret;
|
||||
@ -996,7 +997,7 @@ int gfx_v9_4_ras_error_inject(struct amdgpu_device *adev, void *inject_if)
|
||||
static const struct soc15_reg_entry gfx_v9_4_rdrsp_status_regs =
|
||||
{ SOC15_REG_ENTRY(GC, 0, mmGCEA_ERR_STATUS), 0, 1, 32 };
|
||||
|
||||
void gfx_v9_4_query_ras_error_status(struct amdgpu_device *adev)
|
||||
static void gfx_v9_4_query_ras_error_status(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t i, j;
|
||||
uint32_t reg_value;
|
||||
@ -1021,3 +1022,12 @@ void gfx_v9_4_query_ras_error_status(struct amdgpu_device *adev)
|
||||
gfx_v9_4_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
}
|
||||
|
||||
const struct amdgpu_gfx_ras_funcs gfx_v9_4_ras_funcs = {
|
||||
.ras_late_init = amdgpu_gfx_ras_late_init,
|
||||
.ras_fini = amdgpu_gfx_ras_fini,
|
||||
.ras_error_inject = &gfx_v9_4_ras_error_inject,
|
||||
.query_ras_error_count = &gfx_v9_4_query_ras_error_count,
|
||||
.reset_ras_error_count = &gfx_v9_4_reset_ras_error_count,
|
||||
.query_ras_error_status = &gfx_v9_4_query_ras_error_status,
|
||||
};
|
||||
|
@ -24,16 +24,6 @@
|
||||
#ifndef __GFX_V9_4_H__
|
||||
#define __GFX_V9_4_H__
|
||||
|
||||
void gfx_v9_4_clear_ras_edc_counter(struct amdgpu_device *adev);
|
||||
|
||||
int gfx_v9_4_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
|
||||
int gfx_v9_4_ras_error_inject(struct amdgpu_device *adev,
|
||||
void *inject_if);
|
||||
|
||||
void gfx_v9_4_reset_ras_error_count(struct amdgpu_device *adev);
|
||||
|
||||
void gfx_v9_4_query_ras_error_status(struct amdgpu_device *adev);
|
||||
extern const struct amdgpu_gfx_ras_funcs gfx_v9_4_ras_funcs;
|
||||
|
||||
#endif /* __GFX_V9_4_H__ */
|
||||
|
@ -1283,4 +1283,15 @@ static void gfx_v9_4_2_reset_sq_timeout_status(struct amdgpu_device *adev)
|
||||
}
|
||||
gfx_v9_4_2_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
|
||||
mutex_unlock(&adev->grbm_idx_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
const struct amdgpu_gfx_ras_funcs gfx_v9_4_2_ras_funcs = {
|
||||
.ras_late_init = amdgpu_gfx_ras_late_init,
|
||||
.ras_fini = amdgpu_gfx_ras_fini,
|
||||
.ras_error_inject = &gfx_v9_4_2_ras_error_inject,
|
||||
.query_ras_error_count = &gfx_v9_4_2_query_ras_error_count,
|
||||
.reset_ras_error_count = &gfx_v9_4_2_reset_ras_error_count,
|
||||
.query_ras_error_status = &gfx_v9_4_2_query_ras_error_status,
|
||||
.reset_ras_error_status = &gfx_v9_4_2_reset_ras_error_status,
|
||||
.enable_watchdog_timer = &gfx_v9_4_2_enable_watchdog_timer,
|
||||
};
|
||||
|
@ -30,11 +30,6 @@ void gfx_v9_4_2_init_golden_registers(struct amdgpu_device *adev,
|
||||
uint32_t die_id);
|
||||
void gfx_v9_4_2_set_power_brake_sequence(struct amdgpu_device *adev);
|
||||
|
||||
void gfx_v9_4_2_reset_ras_error_count(struct amdgpu_device *adev);
|
||||
int gfx_v9_4_2_ras_error_inject(struct amdgpu_device *adev, void *inject_if);
|
||||
void gfx_v9_4_2_query_ras_error_status(struct amdgpu_device *adev);
|
||||
int gfx_v9_4_2_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status);
|
||||
void gfx_v9_4_2_reset_ras_error_status(struct amdgpu_device *adev);
|
||||
void gfx_v9_4_2_enable_watchdog_timer(struct amdgpu_device *adev);
|
||||
extern const struct amdgpu_gfx_ras_funcs gfx_v9_4_2_ras_funcs;
|
||||
|
||||
#endif /* __GFX_V9_4_2_H__ */
|
||||
|
@ -655,7 +655,7 @@ static void gmc_v10_0_set_umc_funcs(struct amdgpu_device *adev)
|
||||
adev->umc.umc_inst_num = UMC_V8_7_UMC_INSTANCE_NUM;
|
||||
adev->umc.channel_offs = UMC_V8_7_PER_CHANNEL_OFFSET_SIENNA;
|
||||
adev->umc.channel_idx_tbl = &umc_v8_7_channel_idx_tbl[0][0];
|
||||
adev->umc.funcs = &umc_v8_7_funcs;
|
||||
adev->umc.ras_funcs = &umc_v8_7_ras_funcs;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -653,7 +653,8 @@ static void gmc_v9_0_set_irq_funcs(struct amdgpu_device *adev)
|
||||
adev->gmc.vm_fault.num_types = 1;
|
||||
adev->gmc.vm_fault.funcs = &gmc_v9_0_irq_funcs;
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
if (!amdgpu_sriov_vf(adev) &&
|
||||
!adev->gmc.xgmi.connected_to_cpu) {
|
||||
adev->gmc.ecc_irq.num_types = 1;
|
||||
adev->gmc.ecc_irq.funcs = &gmc_v9_0_ecc_funcs;
|
||||
}
|
||||
@ -1155,7 +1156,7 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
|
||||
adev->umc.umc_inst_num = UMC_V6_1_UMC_INSTANCE_NUM;
|
||||
adev->umc.channel_offs = UMC_V6_1_PER_CHANNEL_OFFSET_VG20;
|
||||
adev->umc.channel_idx_tbl = &umc_v6_1_channel_idx_tbl[0][0];
|
||||
adev->umc.funcs = &umc_v6_1_funcs;
|
||||
adev->umc.ras_funcs = &umc_v6_1_ras_funcs;
|
||||
break;
|
||||
case CHIP_ARCTURUS:
|
||||
adev->umc.max_ras_err_cnt_per_query = UMC_V6_1_TOTAL_CHANNEL_NUM;
|
||||
@ -1163,7 +1164,7 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev)
|
||||
adev->umc.umc_inst_num = UMC_V6_1_UMC_INSTANCE_NUM;
|
||||
adev->umc.channel_offs = UMC_V6_1_PER_CHANNEL_OFFSET_ARCT;
|
||||
adev->umc.channel_idx_tbl = &umc_v6_1_channel_idx_tbl[0][0];
|
||||
adev->umc.funcs = &umc_v6_1_funcs;
|
||||
adev->umc.ras_funcs = &umc_v6_1_ras_funcs;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -1185,6 +1186,24 @@ static void gmc_v9_0_set_mmhub_funcs(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
static void gmc_v9_0_set_mmhub_ras_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA20:
|
||||
adev->mmhub.ras_funcs = &mmhub_v1_0_ras_funcs;
|
||||
break;
|
||||
case CHIP_ARCTURUS:
|
||||
adev->mmhub.ras_funcs = &mmhub_v9_4_ras_funcs;
|
||||
break;
|
||||
case CHIP_ALDEBARAN:
|
||||
adev->mmhub.ras_funcs = &mmhub_v1_7_ras_funcs;
|
||||
break;
|
||||
default:
|
||||
/* mmhub ras is not available */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void gmc_v9_0_set_gfxhub_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->gfxhub.funcs = &gfxhub_v1_0_funcs;
|
||||
@ -1194,12 +1213,6 @@ static int gmc_v9_0_early_init(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
gmc_v9_0_set_gmc_funcs(adev);
|
||||
gmc_v9_0_set_irq_funcs(adev);
|
||||
gmc_v9_0_set_umc_funcs(adev);
|
||||
gmc_v9_0_set_mmhub_funcs(adev);
|
||||
gmc_v9_0_set_gfxhub_funcs(adev);
|
||||
|
||||
if (adev->asic_type == CHIP_VEGA20 ||
|
||||
adev->asic_type == CHIP_ARCTURUS)
|
||||
adev->gmc.xgmi.supported = true;
|
||||
@ -1208,7 +1221,14 @@ static int gmc_v9_0_early_init(void *handle)
|
||||
adev->gmc.xgmi.supported = true;
|
||||
adev->gmc.xgmi.connected_to_cpu =
|
||||
adev->smuio.funcs->is_host_gpu_xgmi_supported(adev);
|
||||
}
|
||||
}
|
||||
|
||||
gmc_v9_0_set_gmc_funcs(adev);
|
||||
gmc_v9_0_set_irq_funcs(adev);
|
||||
gmc_v9_0_set_umc_funcs(adev);
|
||||
gmc_v9_0_set_mmhub_funcs(adev);
|
||||
gmc_v9_0_set_mmhub_ras_funcs(adev);
|
||||
gmc_v9_0_set_gfxhub_funcs(adev);
|
||||
|
||||
adev->gmc.shared_aperture_start = 0x2000000000000000ULL;
|
||||
adev->gmc.shared_aperture_end =
|
||||
@ -1240,8 +1260,9 @@ static int gmc_v9_0_late_init(void *handle)
|
||||
}
|
||||
}
|
||||
|
||||
if (adev->mmhub.funcs && adev->mmhub.funcs->reset_ras_error_count)
|
||||
adev->mmhub.funcs->reset_ras_error_count(adev);
|
||||
if (adev->mmhub.ras_funcs &&
|
||||
adev->mmhub.ras_funcs->reset_ras_error_count)
|
||||
adev->mmhub.ras_funcs->reset_ras_error_count(adev);
|
||||
|
||||
r = amdgpu_gmc_ras_late_init(adev);
|
||||
if (r)
|
||||
@ -1506,7 +1527,8 @@ static int gmc_v9_0_sw_init(void *handle)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (!amdgpu_sriov_vf(adev)) {
|
||||
if (!amdgpu_sriov_vf(adev) &&
|
||||
!adev->gmc.xgmi.connected_to_cpu) {
|
||||
/* interrupt sent to DF. */
|
||||
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DF, 0,
|
||||
&adev->gmc.ecc_irq);
|
||||
|
@ -487,7 +487,7 @@ int jpeg_v1_0_sw_init(void *handle)
|
||||
ring = &adev->jpeg.inst->ring_dec;
|
||||
sprintf(ring->name, "jpeg_dec");
|
||||
r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq,
|
||||
0, AMDGPU_RING_PRIO_DEFAULT);
|
||||
0, AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -108,7 +108,7 @@ static int jpeg_v2_0_sw_init(void *handle)
|
||||
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1;
|
||||
sprintf(ring->name, "jpeg_dec");
|
||||
r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq,
|
||||
0, AMDGPU_RING_PRIO_DEFAULT);
|
||||
0, AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -115,7 +115,7 @@ static int jpeg_v2_5_sw_init(void *handle)
|
||||
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1 + 8 * i;
|
||||
sprintf(ring->name, "jpeg_dec_%d", i);
|
||||
r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst[i].irq,
|
||||
0, AMDGPU_RING_PRIO_DEFAULT);
|
||||
0, AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -94,7 +94,7 @@ static int jpeg_v3_0_sw_init(void *handle)
|
||||
ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1;
|
||||
sprintf(ring->name, "jpeg_dec");
|
||||
r = amdgpu_ring_init(adev, ring, 512, &adev->jpeg.inst->irq, 0,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -848,7 +848,8 @@ static int mes_v10_1_ring_init(struct amdgpu_device *adev)
|
||||
ring->no_scheduler = true;
|
||||
sprintf(ring->name, "mes_%d.%d.%d", ring->me, ring->pipe, ring->queue);
|
||||
|
||||
return amdgpu_ring_init(adev, ring, 1024, NULL, 0, AMDGPU_RING_PRIO_DEFAULT);
|
||||
return amdgpu_ring_init(adev, ring, 1024, NULL, 0,
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
}
|
||||
|
||||
static int mes_v10_1_mqd_sw_init(struct amdgpu_device *adev)
|
||||
|
@ -776,10 +776,14 @@ static void mmhub_v1_0_reset_ras_error_count(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
const struct amdgpu_mmhub_funcs mmhub_v1_0_funcs = {
|
||||
const struct amdgpu_mmhub_ras_funcs mmhub_v1_0_ras_funcs = {
|
||||
.ras_late_init = amdgpu_mmhub_ras_late_init,
|
||||
.ras_fini = amdgpu_mmhub_ras_fini,
|
||||
.query_ras_error_count = mmhub_v1_0_query_ras_error_count,
|
||||
.reset_ras_error_count = mmhub_v1_0_reset_ras_error_count,
|
||||
};
|
||||
|
||||
const struct amdgpu_mmhub_funcs mmhub_v1_0_funcs = {
|
||||
.get_fb_location = mmhub_v1_0_get_fb_location,
|
||||
.init = mmhub_v1_0_init,
|
||||
.gart_enable = mmhub_v1_0_gart_enable,
|
||||
|
@ -24,5 +24,6 @@
|
||||
#define __MMHUB_V1_0_H__
|
||||
|
||||
extern const struct amdgpu_mmhub_funcs mmhub_v1_0_funcs;
|
||||
extern const struct amdgpu_mmhub_ras_funcs mmhub_v1_0_ras_funcs;
|
||||
|
||||
#endif
|
||||
|
@ -1313,10 +1313,15 @@ static void mmhub_v1_7_query_ras_error_status(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
const struct amdgpu_mmhub_funcs mmhub_v1_7_funcs = {
|
||||
const struct amdgpu_mmhub_ras_funcs mmhub_v1_7_ras_funcs = {
|
||||
.ras_late_init = amdgpu_mmhub_ras_late_init,
|
||||
.ras_fini = amdgpu_mmhub_ras_fini,
|
||||
.query_ras_error_count = mmhub_v1_7_query_ras_error_count,
|
||||
.reset_ras_error_count = mmhub_v1_7_reset_ras_error_count,
|
||||
.query_ras_error_status = mmhub_v1_7_query_ras_error_status,
|
||||
};
|
||||
|
||||
const struct amdgpu_mmhub_funcs mmhub_v1_7_funcs = {
|
||||
.get_fb_location = mmhub_v1_7_get_fb_location,
|
||||
.init = mmhub_v1_7_init,
|
||||
.gart_enable = mmhub_v1_7_gart_enable,
|
||||
@ -1325,5 +1330,4 @@ const struct amdgpu_mmhub_funcs mmhub_v1_7_funcs = {
|
||||
.set_clockgating = mmhub_v1_7_set_clockgating,
|
||||
.get_clockgating = mmhub_v1_7_get_clockgating,
|
||||
.setup_vm_pt_regs = mmhub_v1_7_setup_vm_pt_regs,
|
||||
.query_ras_error_status = mmhub_v1_7_query_ras_error_status,
|
||||
};
|
||||
|
@ -24,5 +24,6 @@
|
||||
#define __MMHUB_V1_7_H__
|
||||
|
||||
extern const struct amdgpu_mmhub_funcs mmhub_v1_7_funcs;
|
||||
extern const struct amdgpu_mmhub_ras_funcs mmhub_v1_7_ras_funcs;
|
||||
|
||||
#endif
|
||||
|
@ -689,7 +689,6 @@ static void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags)
|
||||
}
|
||||
|
||||
const struct amdgpu_mmhub_funcs mmhub_v2_0_funcs = {
|
||||
.ras_late_init = amdgpu_mmhub_ras_late_init,
|
||||
.init = mmhub_v2_0_init,
|
||||
.gart_enable = mmhub_v2_0_gart_enable,
|
||||
.set_fault_enable_default = mmhub_v2_0_set_fault_enable_default,
|
||||
|
@ -616,7 +616,6 @@ static void mmhub_v2_3_get_clockgating(struct amdgpu_device *adev, u32 *flags)
|
||||
}
|
||||
|
||||
const struct amdgpu_mmhub_funcs mmhub_v2_3_funcs = {
|
||||
.ras_late_init = amdgpu_mmhub_ras_late_init,
|
||||
.init = mmhub_v2_3_init,
|
||||
.gart_enable = mmhub_v2_3_gart_enable,
|
||||
.set_fault_enable_default = mmhub_v2_3_set_fault_enable_default,
|
||||
|
@ -1652,10 +1652,15 @@ static void mmhub_v9_4_query_ras_error_status(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
const struct amdgpu_mmhub_funcs mmhub_v9_4_funcs = {
|
||||
const struct amdgpu_mmhub_ras_funcs mmhub_v9_4_ras_funcs = {
|
||||
.ras_late_init = amdgpu_mmhub_ras_late_init,
|
||||
.ras_fini = amdgpu_mmhub_ras_fini,
|
||||
.query_ras_error_count = mmhub_v9_4_query_ras_error_count,
|
||||
.reset_ras_error_count = mmhub_v9_4_reset_ras_error_count,
|
||||
.query_ras_error_status = mmhub_v9_4_query_ras_error_status,
|
||||
};
|
||||
|
||||
const struct amdgpu_mmhub_funcs mmhub_v9_4_funcs = {
|
||||
.get_fb_location = mmhub_v9_4_get_fb_location,
|
||||
.init = mmhub_v9_4_init,
|
||||
.gart_enable = mmhub_v9_4_gart_enable,
|
||||
@ -1664,5 +1669,4 @@ const struct amdgpu_mmhub_funcs mmhub_v9_4_funcs = {
|
||||
.set_clockgating = mmhub_v9_4_set_clockgating,
|
||||
.get_clockgating = mmhub_v9_4_get_clockgating,
|
||||
.setup_vm_pt_regs = mmhub_v9_4_setup_vm_pt_regs,
|
||||
.query_ras_error_status = mmhub_v9_4_query_ras_error_status,
|
||||
};
|
||||
|
@ -24,5 +24,6 @@
|
||||
#define __MMHUB_V9_4_H__
|
||||
|
||||
extern const struct amdgpu_mmhub_funcs mmhub_v9_4_funcs;
|
||||
extern const struct amdgpu_mmhub_ras_funcs mmhub_v9_4_ras_funcs;
|
||||
|
||||
#endif
|
||||
|
@ -557,6 +557,16 @@ static void nbio_v7_4_enable_doorbell_interrupt(struct amdgpu_device *adev,
|
||||
DOORBELL_INTERRUPT_DISABLE, enable ? 0 : 1);
|
||||
}
|
||||
|
||||
const struct amdgpu_nbio_ras_funcs nbio_v7_4_ras_funcs = {
|
||||
.handle_ras_controller_intr_no_bifring = nbio_v7_4_handle_ras_controller_intr_no_bifring,
|
||||
.handle_ras_err_event_athub_intr_no_bifring = nbio_v7_4_handle_ras_err_event_athub_intr_no_bifring,
|
||||
.init_ras_controller_interrupt = nbio_v7_4_init_ras_controller_interrupt,
|
||||
.init_ras_err_event_athub_interrupt = nbio_v7_4_init_ras_err_event_athub_interrupt,
|
||||
.query_ras_error_count = nbio_v7_4_query_ras_error_count,
|
||||
.ras_late_init = amdgpu_nbio_ras_late_init,
|
||||
.ras_fini = amdgpu_nbio_ras_fini,
|
||||
};
|
||||
|
||||
const struct amdgpu_nbio_funcs nbio_v7_4_funcs = {
|
||||
.get_hdp_flush_req_offset = nbio_v7_4_get_hdp_flush_req_offset,
|
||||
.get_hdp_flush_done_offset = nbio_v7_4_get_hdp_flush_done_offset,
|
||||
@ -577,10 +587,4 @@ const struct amdgpu_nbio_funcs nbio_v7_4_funcs = {
|
||||
.ih_control = nbio_v7_4_ih_control,
|
||||
.init_registers = nbio_v7_4_init_registers,
|
||||
.remap_hdp_registers = nbio_v7_4_remap_hdp_registers,
|
||||
.handle_ras_controller_intr_no_bifring = nbio_v7_4_handle_ras_controller_intr_no_bifring,
|
||||
.handle_ras_err_event_athub_intr_no_bifring = nbio_v7_4_handle_ras_err_event_athub_intr_no_bifring,
|
||||
.init_ras_controller_interrupt = nbio_v7_4_init_ras_controller_interrupt,
|
||||
.init_ras_err_event_athub_interrupt = nbio_v7_4_init_ras_err_event_athub_interrupt,
|
||||
.query_ras_error_count = nbio_v7_4_query_ras_error_count,
|
||||
.ras_late_init = amdgpu_nbio_ras_late_init,
|
||||
};
|
||||
|
@ -28,5 +28,6 @@
|
||||
|
||||
extern const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg;
|
||||
extern const struct amdgpu_nbio_funcs nbio_v7_4_funcs;
|
||||
extern const struct amdgpu_nbio_ras_funcs nbio_v7_4_ras_funcs;
|
||||
|
||||
#endif
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include "amdgpu_vce.h"
|
||||
#include "amdgpu_ucode.h"
|
||||
#include "amdgpu_psp.h"
|
||||
#include "amdgpu_smu.h"
|
||||
#include "atom.h"
|
||||
#include "amd_pcie.h"
|
||||
|
||||
@ -516,21 +515,9 @@ static int nv_asic_mode2_reset(struct amdgpu_device *adev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool nv_asic_supports_baco(struct amdgpu_device *adev)
|
||||
{
|
||||
struct smu_context *smu = &adev->smu;
|
||||
|
||||
if (smu_baco_is_support(smu))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum amd_reset_method
|
||||
nv_asic_reset_method(struct amdgpu_device *adev)
|
||||
{
|
||||
struct smu_context *smu = &adev->smu;
|
||||
|
||||
if (amdgpu_reset_method == AMD_RESET_METHOD_MODE1 ||
|
||||
amdgpu_reset_method == AMD_RESET_METHOD_MODE2 ||
|
||||
amdgpu_reset_method == AMD_RESET_METHOD_BACO ||
|
||||
@ -549,7 +536,7 @@ nv_asic_reset_method(struct amdgpu_device *adev)
|
||||
case CHIP_DIMGREY_CAVEFISH:
|
||||
return AMD_RESET_METHOD_MODE1;
|
||||
default:
|
||||
if (smu_baco_is_support(smu))
|
||||
if (amdgpu_dpm_is_baco_supported(adev))
|
||||
return AMD_RESET_METHOD_BACO;
|
||||
else
|
||||
return AMD_RESET_METHOD_MODE1;
|
||||
@ -559,11 +546,6 @@ nv_asic_reset_method(struct amdgpu_device *adev)
|
||||
static int nv_asic_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct smu_context *smu = &adev->smu;
|
||||
|
||||
/* skip reset on vangogh for now */
|
||||
if (adev->asic_type == CHIP_VANGOGH)
|
||||
return 0;
|
||||
|
||||
switch (nv_asic_reset_method(adev)) {
|
||||
case AMD_RESET_METHOD_PCI:
|
||||
@ -572,13 +554,7 @@ static int nv_asic_reset(struct amdgpu_device *adev)
|
||||
break;
|
||||
case AMD_RESET_METHOD_BACO:
|
||||
dev_info(adev->dev, "BACO reset\n");
|
||||
|
||||
ret = smu_baco_enter(smu);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = smu_baco_exit(smu);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = amdgpu_dpm_baco_reset(adev);
|
||||
break;
|
||||
case AMD_RESET_METHOD_MODE2:
|
||||
dev_info(adev->dev, "MODE2 reset\n");
|
||||
@ -986,7 +962,7 @@ static const struct amdgpu_asic_funcs nv_asic_funcs =
|
||||
.need_full_reset = &nv_need_full_reset,
|
||||
.need_reset_on_init = &nv_need_reset_on_init,
|
||||
.get_pcie_replay_count = &nv_get_pcie_replay_count,
|
||||
.supports_baco = &nv_asic_supports_baco,
|
||||
.supports_baco = &amdgpu_dpm_is_baco_supported,
|
||||
.pre_asic_init = &nv_pre_asic_init,
|
||||
.update_umd_stable_pstate = &nv_update_umd_stable_pstate,
|
||||
.query_video_codecs = &nv_query_video_codecs,
|
||||
|
@ -102,6 +102,21 @@ enum psp_gfx_cmd_id
|
||||
/* IDs upto 0x1F are reserved for older programs (Raven, Vega 10/12/20) */
|
||||
GFX_CMD_ID_LOAD_TOC = 0x00000020, /* Load TOC and obtain TMR size */
|
||||
GFX_CMD_ID_AUTOLOAD_RLC = 0x00000021, /* Indicates all graphics fw loaded, start RLC autoload */
|
||||
GFX_CMD_ID_BOOT_CFG = 0x00000022, /* Boot Config */
|
||||
};
|
||||
|
||||
/* PSP boot config sub-commands */
|
||||
enum psp_gfx_boot_config_cmd
|
||||
{
|
||||
BOOTCFG_CMD_SET = 1, /* Set boot configuration settings */
|
||||
BOOTCFG_CMD_GET = 2, /* Get boot configuration settings */
|
||||
BOOTCFG_CMD_INVALIDATE = 3 /* Reset current boot configuration settings to VBIOS defaults */
|
||||
};
|
||||
|
||||
/* PSP boot config bitmask values */
|
||||
enum psp_gfx_boot_config
|
||||
{
|
||||
BOOT_CONFIG_GECC = 0x1,
|
||||
};
|
||||
|
||||
/* Command to load Trusted Application binary into PSP OS. */
|
||||
@ -273,6 +288,15 @@ struct psp_gfx_cmd_load_toc
|
||||
uint32_t toc_size; /* FW buffer size in bytes */
|
||||
};
|
||||
|
||||
/* Dynamic boot configuration */
|
||||
struct psp_gfx_cmd_boot_cfg
|
||||
{
|
||||
uint32_t timestamp; /* calendar time as number of seconds */
|
||||
enum psp_gfx_boot_config_cmd sub_cmd; /* sub-command indicating how to process command data */
|
||||
uint32_t boot_config; /* dynamic boot configuration bitmask */
|
||||
uint32_t boot_config_valid; /* dynamic boot configuration valid bits bitmask */
|
||||
};
|
||||
|
||||
/* All GFX ring buffer commands. */
|
||||
union psp_gfx_commands
|
||||
{
|
||||
@ -285,6 +309,7 @@ union psp_gfx_commands
|
||||
struct psp_gfx_cmd_reg_prog cmd_setup_reg_prog;
|
||||
struct psp_gfx_cmd_setup_tmr cmd_setup_vmr;
|
||||
struct psp_gfx_cmd_load_toc cmd_load_toc;
|
||||
struct psp_gfx_cmd_boot_cfg boot_cfg;
|
||||
};
|
||||
|
||||
struct psp_gfx_uresp_reserved
|
||||
|
@ -598,7 +598,7 @@ static int psp_v11_0_memory_training_send_msg(struct psp_context *psp, int msg)
|
||||
}
|
||||
|
||||
/*
|
||||
* save and restore proces
|
||||
* save and restore process
|
||||
*/
|
||||
static int psp_v11_0_memory_training(struct psp_context *psp, uint32_t ops)
|
||||
{
|
||||
@ -661,9 +661,9 @@ static int psp_v11_0_memory_training(struct psp_context *psp, uint32_t ops)
|
||||
|
||||
if (ops & PSP_MEM_TRAIN_SEND_LONG_MSG) {
|
||||
/*
|
||||
* Long traing will encroach certain mount of bottom VRAM,
|
||||
* saving the content of this bottom VRAM to system memory
|
||||
* before training, and restoring it after training to avoid
|
||||
* Long training will encroach a certain amount on the bottom of VRAM;
|
||||
* save the content from the bottom of VRAM to system memory
|
||||
* before training, and restore it after training to avoid
|
||||
* VRAM corruption.
|
||||
*/
|
||||
sz = GDDR6_MEM_TRAINING_ENCROACHED_SIZE;
|
||||
|
@ -876,12 +876,10 @@ static int sdma_v2_4_sw_init(void *handle)
|
||||
ring->ring_obj = NULL;
|
||||
ring->use_doorbell = false;
|
||||
sprintf(ring->name, "sdma%d", i);
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->sdma.trap_irq,
|
||||
(i == 0) ?
|
||||
AMDGPU_SDMA_IRQ_INSTANCE0 :
|
||||
r = amdgpu_ring_init(adev, ring, 1024, &adev->sdma.trap_irq,
|
||||
(i == 0) ? AMDGPU_SDMA_IRQ_INSTANCE0 :
|
||||
AMDGPU_SDMA_IRQ_INSTANCE1,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -1160,12 +1160,10 @@ static int sdma_v3_0_sw_init(void *handle)
|
||||
}
|
||||
|
||||
sprintf(ring->name, "sdma%d", i);
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->sdma.trap_irq,
|
||||
(i == 0) ?
|
||||
AMDGPU_SDMA_IRQ_INSTANCE0 :
|
||||
r = amdgpu_ring_init(adev, ring, 1024, &adev->sdma.trap_irq,
|
||||
(i == 0) ? AMDGPU_SDMA_IRQ_INSTANCE0 :
|
||||
AMDGPU_SDMA_IRQ_INSTANCE1,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -1968,7 +1968,7 @@ static int sdma_v4_0_sw_init(void *handle)
|
||||
sprintf(ring->name, "sdma%d", i);
|
||||
r = amdgpu_ring_init(adev, ring, 1024, &adev->sdma.trap_irq,
|
||||
AMDGPU_SDMA_IRQ_INSTANCE0 + i,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@ -1987,7 +1987,7 @@ static int sdma_v4_0_sw_init(void *handle)
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->sdma.trap_irq,
|
||||
AMDGPU_SDMA_IRQ_INSTANCE0 + i,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -1273,12 +1273,10 @@ static int sdma_v5_0_sw_init(void *handle)
|
||||
: (adev->doorbell_index.sdma_engine[1] << 1); // get DWORD offset
|
||||
|
||||
sprintf(ring->name, "sdma%d", i);
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->sdma.trap_irq,
|
||||
(i == 0) ?
|
||||
AMDGPU_SDMA_IRQ_INSTANCE0 :
|
||||
r = amdgpu_ring_init(adev, ring, 1024, &adev->sdma.trap_irq,
|
||||
(i == 0) ? AMDGPU_SDMA_IRQ_INSTANCE0 :
|
||||
AMDGPU_SDMA_IRQ_INSTANCE1,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -1283,10 +1283,9 @@ static int sdma_v5_2_sw_init(void *handle)
|
||||
(adev->doorbell_index.sdma_engine[i] << 1); //get DWORD offset
|
||||
|
||||
sprintf(ring->name, "sdma%d", i);
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->sdma.trap_irq,
|
||||
r = amdgpu_ring_init(adev, ring, 1024, &adev->sdma.trap_irq,
|
||||
AMDGPU_SDMA_IRQ_INSTANCE0 + i,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -507,10 +507,9 @@ static int si_dma_sw_init(void *handle)
|
||||
sprintf(ring->name, "sdma%d", i);
|
||||
r = amdgpu_ring_init(adev, ring, 1024,
|
||||
&adev->sdma.trap_irq,
|
||||
(i == 0) ?
|
||||
AMDGPU_SDMA_IRQ_INSTANCE0 :
|
||||
(i == 0) ? AMDGPU_SDMA_IRQ_INSTANCE0 :
|
||||
AMDGPU_SDMA_IRQ_INSTANCE1,
|
||||
AMDGPU_RING_PRIO_DEFAULT);
|
||||
AMDGPU_RING_PRIO_DEFAULT, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -76,7 +76,6 @@
|
||||
#include "smuio_v13_0.h"
|
||||
#include "dce_virtual.h"
|
||||
#include "mxgpu_ai.h"
|
||||
#include "amdgpu_smu.h"
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_xgmi.h"
|
||||
#include <uapi/linux/kfd_ioctl.h>
|
||||
@ -1495,8 +1494,8 @@ static int soc15_common_early_init(void *handle)
|
||||
AMD_CG_SUPPORT_HDP_LS |
|
||||
AMD_CG_SUPPORT_SDMA_MGCG |
|
||||
AMD_CG_SUPPORT_SDMA_LS |
|
||||
AMD_CG_SUPPORT_IH_CG;
|
||||
/*AMD_CG_SUPPORT_VCN_MGCG |AMD_CG_SUPPORT_JPEG_MGCG;*/
|
||||
AMD_CG_SUPPORT_IH_CG |
|
||||
AMD_CG_SUPPORT_VCN_MGCG | AMD_CG_SUPPORT_JPEG_MGCG;
|
||||
adev->pg_flags = AMD_PG_SUPPORT_VCN_DPG;
|
||||
adev->external_rev_id = adev->rev_id + 0x3c;
|
||||
break;
|
||||
@ -1524,8 +1523,9 @@ static int soc15_common_late_init(void *handle)
|
||||
if (adev->hdp.funcs->reset_ras_error_count)
|
||||
adev->hdp.funcs->reset_ras_error_count(adev);
|
||||
|
||||
if (adev->nbio.funcs->ras_late_init)
|
||||
r = adev->nbio.funcs->ras_late_init(adev);
|
||||
if (adev->nbio.ras_funcs &&
|
||||
adev->nbio.ras_funcs->ras_late_init)
|
||||
r = adev->nbio.ras_funcs->ras_late_init(adev);
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -1546,7 +1546,9 @@ static int soc15_common_sw_fini(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
amdgpu_nbio_ras_fini(adev);
|
||||
if (adev->nbio.ras_funcs &&
|
||||
adev->nbio.ras_funcs->ras_fini)
|
||||
adev->nbio.ras_funcs->ras_fini(adev);
|
||||
adev->df.funcs->sw_fini(adev);
|
||||
return 0;
|
||||
}
|
||||
@ -1610,9 +1612,11 @@ static int soc15_common_hw_fini(void *handle)
|
||||
|
||||
if (adev->nbio.ras_if &&
|
||||
amdgpu_ras_is_supported(adev, adev->nbio.ras_if->block)) {
|
||||
if (adev->nbio.funcs->init_ras_controller_interrupt)
|
||||
if (adev->nbio.ras_funcs &&
|
||||
adev->nbio.ras_funcs->init_ras_controller_interrupt)
|
||||
amdgpu_irq_put(adev, &adev->nbio.ras_controller_irq, 0);
|
||||
if (adev->nbio.funcs->init_ras_err_event_athub_interrupt)
|
||||
if (adev->nbio.ras_funcs &&
|
||||
adev->nbio.ras_funcs->init_ras_err_event_athub_interrupt)
|
||||
amdgpu_irq_put(adev, &adev->nbio.ras_err_event_athub_irq, 0);
|
||||
}
|
||||
|
||||
|
@ -77,27 +77,11 @@
|
||||
})
|
||||
|
||||
#define WREG32_RLC(reg, value) \
|
||||
do { \
|
||||
if (amdgpu_sriov_fullaccess(adev)) { \
|
||||
uint32_t i = 0; \
|
||||
uint32_t retries = 50000; \
|
||||
uint32_t r0 = adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG0_BASE_IDX] + mmSCRATCH_REG0; \
|
||||
uint32_t r1 = adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG1_BASE_IDX] + mmSCRATCH_REG1; \
|
||||
uint32_t spare_int = adev->reg_offset[GC_HWIP][0][mmRLC_SPARE_INT_BASE_IDX] + mmRLC_SPARE_INT; \
|
||||
WREG32(r0, value); \
|
||||
WREG32(r1, (reg | 0x80000000)); \
|
||||
WREG32(spare_int, 0x1); \
|
||||
for (i = 0; i < retries; i++) { \
|
||||
u32 tmp = RREG32(r1); \
|
||||
if (!(tmp & 0x80000000)) \
|
||||
break; \
|
||||
udelay(10); \
|
||||
} \
|
||||
if (i >= retries) \
|
||||
pr_err("timeout: rlcg program reg:0x%05x failed !\n", reg); \
|
||||
} else { \
|
||||
WREG32(reg, value); \
|
||||
} \
|
||||
do { \
|
||||
if (adev->gfx.rlc.funcs->rlcg_wreg) \
|
||||
adev->gfx.rlc.funcs->rlcg_wreg(adev, reg, value, 0); \
|
||||
else \
|
||||
WREG32(reg, value); \
|
||||
} while (0)
|
||||
|
||||
#define WREG32_RLC_EX(prefix, reg, value) \
|
||||
@ -125,23 +109,24 @@
|
||||
} while (0)
|
||||
|
||||
#define WREG32_SOC15_RLC_SHADOW(ip, inst, reg, value) \
|
||||
do { \
|
||||
uint32_t target_reg = adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg;\
|
||||
if (amdgpu_sriov_fullaccess(adev)) { \
|
||||
uint32_t r2 = adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG1_BASE_IDX] + mmSCRATCH_REG2; \
|
||||
uint32_t r3 = adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG1_BASE_IDX] + mmSCRATCH_REG3; \
|
||||
uint32_t grbm_cntl = adev->reg_offset[GC_HWIP][0][mmGRBM_GFX_CNTL_BASE_IDX] + mmGRBM_GFX_CNTL; \
|
||||
uint32_t grbm_idx = adev->reg_offset[GC_HWIP][0][mmGRBM_GFX_INDEX_BASE_IDX] + mmGRBM_GFX_INDEX; \
|
||||
if (target_reg == grbm_cntl) \
|
||||
WREG32(r2, value); \
|
||||
else if (target_reg == grbm_idx) \
|
||||
WREG32(r3, value); \
|
||||
WREG32(target_reg, value); \
|
||||
} else { \
|
||||
WREG32(target_reg, value); \
|
||||
} \
|
||||
WREG32_RLC((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg), value)
|
||||
|
||||
#define RREG32_RLC(reg) \
|
||||
(adev->gfx.rlc.funcs->rlcg_rreg ? \
|
||||
adev->gfx.rlc.funcs->rlcg_rreg(adev, reg, 0) : RREG32(reg))
|
||||
|
||||
#define WREG32_RLC_NO_KIQ(reg, value) \
|
||||
do { \
|
||||
if (adev->gfx.rlc.funcs->rlcg_wreg) \
|
||||
adev->gfx.rlc.funcs->rlcg_wreg(adev, reg, value, AMDGPU_REGS_NO_KIQ); \
|
||||
else \
|
||||
WREG32_NO_KIQ(reg, value); \
|
||||
} while (0)
|
||||
|
||||
#define RREG32_RLC_NO_KIQ(reg) \
|
||||
(adev->gfx.rlc.funcs->rlcg_rreg ? \
|
||||
adev->gfx.rlc.funcs->rlcg_rreg(adev, reg, AMDGPU_REGS_NO_KIQ) : RREG32_NO_KIQ(reg))
|
||||
|
||||
#define WREG32_SOC15_RLC_SHADOW_EX(prefix, ip, inst, reg, value) \
|
||||
do { \
|
||||
uint32_t target_reg = adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg;\
|
||||
@ -160,10 +145,13 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define RREG32_SOC15_RLC(ip, inst, reg) \
|
||||
RREG32_RLC(adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg)
|
||||
|
||||
#define WREG32_SOC15_RLC(ip, inst, reg, value) \
|
||||
do { \
|
||||
uint32_t target_reg = adev->reg_offset[GC_HWIP][0][reg##_BASE_IDX] + reg;\
|
||||
WREG32_RLC(target_reg, value); \
|
||||
uint32_t target_reg = adev->reg_offset[ip##_HWIP][0][reg##_BASE_IDX] + reg;\
|
||||
WREG32_RLC(target_reg, value); \
|
||||
} while (0)
|
||||
|
||||
#define WREG32_SOC15_RLC_EX(prefix, ip, inst, reg, value) \
|
||||
@ -173,11 +161,14 @@
|
||||
} while (0)
|
||||
|
||||
#define WREG32_FIELD15_RLC(ip, idx, reg, field, val) \
|
||||
WREG32_RLC((adev->reg_offset[ip##_HWIP][idx][mm##reg##_BASE_IDX] + mm##reg), \
|
||||
(RREG32(adev->reg_offset[ip##_HWIP][idx][mm##reg##_BASE_IDX] + mm##reg) \
|
||||
& ~REG_FIELD_MASK(reg, field)) | (val) << REG_FIELD_SHIFT(reg, field))
|
||||
WREG32_RLC((adev->reg_offset[ip##_HWIP][idx][mm##reg##_BASE_IDX] + mm##reg), \
|
||||
(RREG32_RLC(adev->reg_offset[ip##_HWIP][idx][mm##reg##_BASE_IDX] + mm##reg) \
|
||||
& ~REG_FIELD_MASK(reg, field)) | (val) << REG_FIELD_SHIFT(reg, field))
|
||||
|
||||
#define WREG32_SOC15_OFFSET_RLC(ip, inst, reg, offset, value) \
|
||||
WREG32_RLC(((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) + offset), value)
|
||||
WREG32_RLC(((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) + offset), value)
|
||||
|
||||
#define RREG32_SOC15_OFFSET_RLC(ip, inst, reg, offset) \
|
||||
RREG32_RLC(((adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) + offset))
|
||||
|
||||
#endif
|
||||
|
@ -22,6 +22,7 @@
|
||||
*/
|
||||
#include "umc_v6_1.h"
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_umc.h"
|
||||
#include "amdgpu.h"
|
||||
|
||||
#include "rsmu/rsmu_0_0_2_offset.h"
|
||||
@ -464,9 +465,10 @@ static void umc_v6_1_err_cnt_init(struct amdgpu_device *adev)
|
||||
umc_v6_1_enable_umc_index_mode(adev);
|
||||
}
|
||||
|
||||
const struct amdgpu_umc_funcs umc_v6_1_funcs = {
|
||||
const struct amdgpu_umc_ras_funcs umc_v6_1_ras_funcs = {
|
||||
.err_cnt_init = umc_v6_1_err_cnt_init,
|
||||
.ras_late_init = amdgpu_umc_ras_late_init,
|
||||
.ras_fini = amdgpu_umc_ras_fini,
|
||||
.query_ras_error_count = umc_v6_1_query_ras_error_count,
|
||||
.query_ras_error_address = umc_v6_1_query_ras_error_address,
|
||||
};
|
||||
|
@ -45,7 +45,7 @@
|
||||
/* umc ce count initial value */
|
||||
#define UMC_V6_1_CE_CNT_INIT (UMC_V6_1_CE_CNT_MAX - UMC_V6_1_CE_INT_THRESHOLD)
|
||||
|
||||
extern const struct amdgpu_umc_funcs umc_v6_1_funcs;
|
||||
extern const struct amdgpu_umc_ras_funcs umc_v6_1_ras_funcs;
|
||||
extern const uint32_t
|
||||
umc_v6_1_channel_idx_tbl[UMC_V6_1_UMC_INSTANCE_NUM][UMC_V6_1_CHANNEL_INSTANCE_NUM];
|
||||
|
||||
|
281
drivers/gpu/drm/amd/amdgpu/umc_v6_7.c
Normal file
281
drivers/gpu/drm/amd/amdgpu/umc_v6_7.c
Normal file
@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Copyright 2021 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#include "umc_v6_7.h"
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_umc.h"
|
||||
#include "amdgpu.h"
|
||||
|
||||
#include "umc/umc_6_7_0_offset.h"
|
||||
#include "umc/umc_6_7_0_sh_mask.h"
|
||||
|
||||
static inline uint32_t get_umc_v6_7_reg_offset(struct amdgpu_device *adev,
|
||||
uint32_t umc_inst,
|
||||
uint32_t ch_inst)
|
||||
{
|
||||
return adev->umc.channel_offs * ch_inst + UMC_V6_7_INST_DIST * umc_inst;
|
||||
}
|
||||
|
||||
static void umc_v6_7_query_correctable_error_count(struct amdgpu_device *adev,
|
||||
uint32_t umc_reg_offset,
|
||||
unsigned long *error_count)
|
||||
{
|
||||
uint32_t ecc_err_cnt_sel, ecc_err_cnt_sel_addr;
|
||||
uint32_t ecc_err_cnt, ecc_err_cnt_addr;
|
||||
uint64_t mc_umc_status;
|
||||
uint32_t mc_umc_status_addr;
|
||||
|
||||
/* UMC 6_1_1 registers */
|
||||
ecc_err_cnt_sel_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, regUMCCH0_0_EccErrCntSel);
|
||||
ecc_err_cnt_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, regUMCCH0_0_EccErrCnt);
|
||||
mc_umc_status_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0);
|
||||
|
||||
/* select the lower chip and check the error count */
|
||||
ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4);
|
||||
ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_EccErrCntSel,
|
||||
EccErrCntCsSel, 0);
|
||||
WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, ecc_err_cnt_sel);
|
||||
|
||||
ecc_err_cnt = RREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4);
|
||||
*error_count +=
|
||||
(REG_GET_FIELD(ecc_err_cnt, UMCCH0_0_EccErrCnt, EccErrCnt) -
|
||||
UMC_V6_7_CE_CNT_INIT);
|
||||
|
||||
/* select the higher chip and check the err counter */
|
||||
ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel, UMCCH0_0_EccErrCntSel,
|
||||
EccErrCntCsSel, 1);
|
||||
WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4, ecc_err_cnt_sel);
|
||||
|
||||
ecc_err_cnt = RREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4);
|
||||
*error_count +=
|
||||
(REG_GET_FIELD(ecc_err_cnt, UMCCH0_0_EccErrCnt, EccErrCnt) -
|
||||
UMC_V6_7_CE_CNT_INIT);
|
||||
|
||||
/* check for SRAM correctable error
|
||||
MCUMC_STATUS is a 64 bit register */
|
||||
mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
|
||||
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
|
||||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)
|
||||
*error_count += 1;
|
||||
}
|
||||
|
||||
static void umc_v6_7_querry_uncorrectable_error_count(struct amdgpu_device *adev,
|
||||
uint32_t umc_reg_offset,
|
||||
unsigned long *error_count)
|
||||
{
|
||||
uint64_t mc_umc_status;
|
||||
uint32_t mc_umc_status_addr;
|
||||
|
||||
mc_umc_status_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0);
|
||||
|
||||
/* check the MCUMC_STATUS */
|
||||
mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
|
||||
if ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) &&
|
||||
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1 ||
|
||||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
|
||||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 ||
|
||||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1 ||
|
||||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, TCC) == 1))
|
||||
*error_count += 1;
|
||||
}
|
||||
|
||||
static void umc_v6_7_reset_error_count_per_channel(struct amdgpu_device *adev,
|
||||
uint32_t umc_reg_offset)
|
||||
{
|
||||
uint32_t ecc_err_cnt_addr;
|
||||
uint32_t ecc_err_cnt_sel, ecc_err_cnt_sel_addr;
|
||||
|
||||
ecc_err_cnt_sel_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0,
|
||||
regUMCCH0_0_EccErrCntSel);
|
||||
ecc_err_cnt_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0,
|
||||
regUMCCH0_0_EccErrCnt);
|
||||
|
||||
/* select the lower chip */
|
||||
ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr +
|
||||
umc_reg_offset) * 4);
|
||||
ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel,
|
||||
UMCCH0_0_EccErrCntSel,
|
||||
EccErrCntCsSel, 0);
|
||||
WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4,
|
||||
ecc_err_cnt_sel);
|
||||
|
||||
/* clear lower chip error count */
|
||||
WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4,
|
||||
UMC_V6_7_CE_CNT_INIT);
|
||||
|
||||
/* select the higher chip */
|
||||
ecc_err_cnt_sel = RREG32_PCIE((ecc_err_cnt_sel_addr +
|
||||
umc_reg_offset) * 4);
|
||||
ecc_err_cnt_sel = REG_SET_FIELD(ecc_err_cnt_sel,
|
||||
UMCCH0_0_EccErrCntSel,
|
||||
EccErrCntCsSel, 1);
|
||||
WREG32_PCIE((ecc_err_cnt_sel_addr + umc_reg_offset) * 4,
|
||||
ecc_err_cnt_sel);
|
||||
|
||||
/* clear higher chip error count */
|
||||
WREG32_PCIE((ecc_err_cnt_addr + umc_reg_offset) * 4,
|
||||
UMC_V6_7_CE_CNT_INIT);
|
||||
}
|
||||
|
||||
static void umc_v6_7_reset_error_count(struct amdgpu_device *adev)
|
||||
{
|
||||
uint32_t umc_inst = 0;
|
||||
uint32_t ch_inst = 0;
|
||||
uint32_t umc_reg_offset = 0;
|
||||
|
||||
LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) {
|
||||
umc_reg_offset = get_umc_v6_7_reg_offset(adev,
|
||||
umc_inst,
|
||||
ch_inst);
|
||||
|
||||
umc_v6_7_reset_error_count_per_channel(adev,
|
||||
umc_reg_offset);
|
||||
}
|
||||
}
|
||||
|
||||
static void umc_v6_7_query_ras_error_count(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
{
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
|
||||
uint32_t umc_inst = 0;
|
||||
uint32_t ch_inst = 0;
|
||||
uint32_t umc_reg_offset = 0;
|
||||
|
||||
/*TODO: driver needs to toggle DF Cstate to ensure
|
||||
* safe access of UMC registers. Will add the protection */
|
||||
LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) {
|
||||
umc_reg_offset = get_umc_v6_7_reg_offset(adev,
|
||||
umc_inst,
|
||||
ch_inst);
|
||||
umc_v6_7_query_correctable_error_count(adev,
|
||||
umc_reg_offset,
|
||||
&(err_data->ce_count));
|
||||
umc_v6_7_querry_uncorrectable_error_count(adev,
|
||||
umc_reg_offset,
|
||||
&(err_data->ue_count));
|
||||
}
|
||||
|
||||
umc_v6_7_reset_error_count(adev);
|
||||
}
|
||||
|
||||
static void umc_v6_7_query_error_address(struct amdgpu_device *adev,
|
||||
struct ras_err_data *err_data,
|
||||
uint32_t umc_reg_offset,
|
||||
uint32_t ch_inst,
|
||||
uint32_t umc_inst)
|
||||
{
|
||||
uint32_t mc_umc_status_addr;
|
||||
uint64_t mc_umc_status, err_addr, retired_page, mc_umc_addrt0;
|
||||
struct eeprom_table_record *err_rec;
|
||||
uint32_t channel_index;
|
||||
|
||||
mc_umc_status_addr =
|
||||
SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0);
|
||||
mc_umc_addrt0 =
|
||||
SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_ADDRT0);
|
||||
|
||||
mc_umc_status = RREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4);
|
||||
|
||||
if (mc_umc_status == 0)
|
||||
return;
|
||||
|
||||
if (!err_data->err_addr) {
|
||||
/* clear umc status */
|
||||
WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
|
||||
return;
|
||||
}
|
||||
|
||||
err_rec = &err_data->err_addr[err_data->err_addr_cnt];
|
||||
|
||||
channel_index =
|
||||
adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst];
|
||||
|
||||
/* calculate error address if ue/ce error is detected */
|
||||
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 &&
|
||||
(REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 ||
|
||||
REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) {
|
||||
|
||||
err_addr = RREG64_PCIE((mc_umc_addrt0 + umc_reg_offset) * 4);
|
||||
err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr);
|
||||
|
||||
/* translate umc channel address to soc pa, 3 parts are included */
|
||||
retired_page = ADDR_OF_8KB_BLOCK(err_addr) |
|
||||
ADDR_OF_256B_BLOCK(channel_index) |
|
||||
OFFSET_IN_256B_BLOCK(err_addr);
|
||||
|
||||
/* we only save ue error information currently, ce is skipped */
|
||||
if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC)
|
||||
== 1) {
|
||||
err_rec->address = err_addr;
|
||||
/* page frame address is saved */
|
||||
err_rec->retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT;
|
||||
err_rec->ts = (uint64_t)ktime_get_real_seconds();
|
||||
err_rec->err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE;
|
||||
err_rec->cu = 0;
|
||||
err_rec->mem_channel = channel_index;
|
||||
err_rec->mcumc_id = umc_inst;
|
||||
|
||||
err_data->err_addr_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
/* clear umc status */
|
||||
WREG64_PCIE((mc_umc_status_addr + umc_reg_offset) * 4, 0x0ULL);
|
||||
}
|
||||
|
||||
static void umc_v6_7_query_ras_error_address(struct amdgpu_device *adev,
|
||||
void *ras_error_status)
|
||||
{
|
||||
struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
|
||||
|
||||
uint32_t umc_inst = 0;
|
||||
uint32_t ch_inst = 0;
|
||||
uint32_t umc_reg_offset = 0;
|
||||
|
||||
/*TODO: driver needs to toggle DF Cstate to ensure
|
||||
* safe access of UMC resgisters. Will add the protection
|
||||
* when firmware interface is ready */
|
||||
LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) {
|
||||
umc_reg_offset = get_umc_v6_7_reg_offset(adev,
|
||||
umc_inst,
|
||||
ch_inst);
|
||||
umc_v6_7_query_error_address(adev,
|
||||
err_data,
|
||||
umc_reg_offset,
|
||||
ch_inst,
|
||||
umc_inst);
|
||||
}
|
||||
}
|
||||
|
||||
const struct amdgpu_umc_ras_funcs umc_v6_7_ras_funcs = {
|
||||
.ras_late_init = amdgpu_umc_ras_late_init,
|
||||
.ras_fini = amdgpu_umc_ras_fini,
|
||||
.query_ras_error_count = umc_v6_7_query_ras_error_count,
|
||||
.query_ras_error_address = umc_v6_7_query_ras_error_address,
|
||||
};
|
37
drivers/gpu/drm/amd/amdgpu/umc_v6_7.h
Normal file
37
drivers/gpu/drm/amd/amdgpu/umc_v6_7.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2021 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
#ifndef __UMC_V6_7_H__
|
||||
#define __UMC_V6_7_H__
|
||||
|
||||
/* EccErrCnt max value */
|
||||
#define UMC_V6_7_CE_CNT_MAX 0xffff
|
||||
/* umc ce interrupt threshold */
|
||||
#define UMC_V6_7_CE_INT_THRESHOLD 0xffff
|
||||
/* umc ce count initial value */
|
||||
#define UMC_V6_7_CE_CNT_INIT (UMC_V6_7_CE_CNT_MAX - UMC_V6_7_CE_INT_THRESHOLD)
|
||||
|
||||
#define UMC_V6_7_INST_DIST 0x40000
|
||||
|
||||
extern const struct amdgpu_umc_ras_funcs umc_v6_7_ras_funcs;
|
||||
|
||||
#endif
|
@ -22,6 +22,7 @@
|
||||
*/
|
||||
#include "umc_v8_7.h"
|
||||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_umc.h"
|
||||
#include "amdgpu.h"
|
||||
|
||||
#include "rsmu/rsmu_0_0_2_offset.h"
|
||||
@ -323,9 +324,10 @@ static void umc_v8_7_err_cnt_init(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
|
||||
const struct amdgpu_umc_funcs umc_v8_7_funcs = {
|
||||
const struct amdgpu_umc_ras_funcs umc_v8_7_ras_funcs = {
|
||||
.err_cnt_init = umc_v8_7_err_cnt_init,
|
||||
.ras_late_init = amdgpu_umc_ras_late_init,
|
||||
.ras_fini = amdgpu_umc_ras_fini,
|
||||
.query_ras_error_count = umc_v8_7_query_ras_error_count,
|
||||
.query_ras_error_address = umc_v8_7_query_ras_error_address,
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user