diff --git a/src/amd/amdgpu/common_baco.c b/src/amd/amdgpu/common_baco.c index 38b74ab..a3e54dc 100644 --- a/src/amd/amdgpu/common_baco.c +++ b/src/amd/amdgpu/common_baco.c @@ -23,6 +23,8 @@ #include #include +#include "soc15_common.h" +#include "vega10_inc.h" #include "common_baco.h" #include "common.h" @@ -120,3 +122,17 @@ bool soc15_baco_program_registers(struct amd_fake_dev *adev, return true; } + +int smu9_baco_get_state(struct amd_fake_dev *adev, enum BACO_STATE *state) +{ + uint32_t reg; + + reg = RREG32_SOC15(NBIF, 0, mmBACO_CNTL); + + if (reg & BACO_CNTL__BACO_MODE_MASK) + /* gfx has already entered BACO state */ + *state = BACO_STATE_IN; + else + *state = BACO_STATE_OUT; + return 0; +} diff --git a/src/amd/amdgpu/common_baco.h b/src/amd/amdgpu/common_baco.h index fdd0aeb..9e377a3 100644 --- a/src/amd/amdgpu/common_baco.h +++ b/src/amd/amdgpu/common_baco.h @@ -55,6 +55,14 @@ struct soc15_baco_cmd_entry uint32_t val; }; +/* from hwmgr.h */ +enum BACO_STATE +{ + BACO_STATE_OUT = 0, + BACO_STATE_IN, +}; +/* end from hwmgr.h */ + struct amd_fake_dev; extern bool baco_program_registers(struct amd_fake_dev *adev, @@ -63,4 +71,6 @@ extern bool baco_program_registers(struct amd_fake_dev *adev, extern bool soc15_baco_program_registers(struct amd_fake_dev *adev, const struct soc15_baco_cmd_entry *entry, const u32 array_size); +extern int smu9_baco_get_state(struct amd_fake_dev *adev, enum BACO_STATE *state); + #endif diff --git a/src/amd/common.h b/src/amd/common.h index 4f91273..d7a6b08 100644 --- a/src/amd/common.h +++ b/src/amd/common.h @@ -144,14 +144,6 @@ enum amd_hw_ip_block_type #define HWIP_MAX_INSTANCE 8 /* end from amdgpu.h */ -/* from hwmgr.h */ -enum BACO_STATE -{ - BACO_STATE_OUT = 0, - BACO_STATE_IN, -}; -/* end from hwmgr.h */ - struct amd_fake_dev { uint32_t *reg_offset[MAX_HWIP][HWIP_MAX_INSTANCE]; diff --git a/src/amd/vega10.c b/src/amd/vega10.c index 9a649e3..052bdf6 100644 --- a/src/amd/vega10.c +++ b/src/amd/vega10.c @@ -128,6 +128,7 @@ static int amd_vega10_reset(struct vendor_reset_dev *dev) struct amd_fake_dev *adev; int ret, timeout; u32 sol, smu_resp, mp1_intr, psp_bl_ready; + enum BACO_STATE baco_state; priv->adev = (struct amd_fake_dev){ .dev = &dev->pdev->dev, @@ -156,22 +157,31 @@ static int amd_vega10_reset(struct vendor_reset_dev *dev) MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >> MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT; psp_bl_ready = !!(RREG32(mmMP0_SMN_C2PMSG_35) & 0x80000000L); + smu9_baco_get_state(adev, &baco_state); pci_info( dev->pdev, - "Vega10: SMU response reg: %x, sol reg: %x, mp1 intr enabled? %s, bl ready? %s\n", + "Vega10: SMU response reg: %x, sol reg: %x, mp1 intr enabled? %s, bl ready? %s, baco? %s\n", smu_resp, sol, mp1_intr ? "yes" : "no", - psp_bl_ready ? "yes" : "no"); + psp_bl_ready ? "yes" : "no", + baco_state == BACO_STATE_IN ? "on" : "off"); - if (sol == ~1L) + if (sol == ~1L && baco_state != BACO_STATE_IN) { pci_warn(dev->pdev, "Vega10: Timed out waiting for SOL to be valid\n"); return -EINVAL; } - pci_info(dev->pdev, "Vega10: Entering BACO\n"); - ret = vega10_baco_set_state(adev, BACO_STATE_IN); - if (ret) - return ret; + /* if there's no sign of life we usually can't reset */ + if (!sol) + return 0; + + if (baco_state == BACO_STATE_OUT) + { + pci_info(dev->pdev, "Vega10: Entering BACO\n"); + ret = vega10_baco_set_state(adev, BACO_STATE_IN); + if (ret) + return ret; + } pci_info(dev->pdev, "Vega10: Exiting BACO\n"); ret = vega10_baco_set_state(adev, BACO_STATE_OUT);