Commit 8345a71f authored by Lijo Lazar's avatar Lijo Lazar Committed by Alex Deucher
Browse files

drm/amdgpu: Add more checks to PSP mailbox



Instead of checking the response flag, use status mask also to check
against any unexpected failures like a device drop. Also, log error if
waiting on a psp response fails/times out.

Signed-off-by: default avatarLijo Lazar <lijo.lazar@amd.com>
Reviewed-by: default avatarHawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 5562b669
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -597,6 +597,10 @@ int psp_wait_for(struct psp_context *psp, uint32_t reg_index,
		udelay(1);
	}

	dev_err(adev->dev,
		"psp reg (0x%x) wait timed out, mask: %x, read: %x exp: %x",
		reg_index, mask, val, reg_val);

	return -ETIME;
}

+11 −0
Original line number Diff line number Diff line
@@ -51,6 +51,17 @@
#define C2PMSG_CMD_SPI_GET_ROM_IMAGE_ADDR_HI 0x10
#define C2PMSG_CMD_SPI_GET_FLASH_IMAGE 0x11

/* Command register bit 31 set to indicate readiness */
#define MBOX_TOS_READY_FLAG (GFX_FLAG_RESPONSE)
#define MBOX_TOS_READY_MASK (GFX_CMD_RESPONSE_MASK | GFX_CMD_STATUS_MASK)

/* Values to check for a successful GFX_CMD response wait. Check against
 * both status bits and response state - helps to detect a command failure
 * or other unexpected cases like a device drop reading all 0xFFs
 */
#define MBOX_TOS_RESP_FLAG (GFX_FLAG_RESPONSE)
#define MBOX_TOS_RESP_MASK (GFX_CMD_RESPONSE_MASK | GFX_CMD_STATUS_MASK)

extern const struct attribute_group amdgpu_flash_attr_group;

enum psp_shared_mem_size {
+2 −2
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ static int psp_v10_0_ring_create(struct psp_context *psp,

	/* Wait for response flag (bit 31) in C2PMSG_64 */
	ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
			   0x80000000, 0x8000FFFF, false);
			   MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);

	return ret;
}
@@ -115,7 +115,7 @@ static int psp_v10_0_ring_stop(struct psp_context *psp,

	/* Wait for response flag (bit 31) in C2PMSG_64 */
	ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
			   0x80000000, 0x80000000, false);
			   MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);

	return ret;
}
+19 −12
Original line number Diff line number Diff line
@@ -277,11 +277,13 @@ static int psp_v11_0_ring_stop(struct psp_context *psp,

	/* Wait for response flag (bit 31) */
	if (amdgpu_sriov_vf(adev))
		ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
				   0x80000000, 0x80000000, false);
		ret = psp_wait_for(
			psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
			MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
	else
		ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
				   0x80000000, 0x80000000, false);
		ret = psp_wait_for(
			psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
			MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);

	return ret;
}
@@ -317,13 +319,15 @@ static int psp_v11_0_ring_create(struct psp_context *psp,
		mdelay(20);

		/* Wait for response flag (bit 31) in C2PMSG_101 */
		ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
				   0x80000000, 0x8000FFFF, false);
		ret = psp_wait_for(
			psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
			MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);

	} else {
		/* Wait for sOS ready for ring creation */
		ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
				   0x80000000, 0x80000000, false);
		ret = psp_wait_for(
			psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
			MBOX_TOS_READY_FLAG, MBOX_TOS_READY_MASK, false);
		if (ret) {
			DRM_ERROR("Failed to wait for sOS ready for ring creation\n");
			return ret;
@@ -347,8 +351,9 @@ static int psp_v11_0_ring_create(struct psp_context *psp,
		mdelay(20);

		/* Wait for response flag (bit 31) in C2PMSG_64 */
		ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
				   0x80000000, 0x8000FFFF, false);
		ret = psp_wait_for(
			psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
			MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
	}

	return ret;
@@ -381,7 +386,8 @@ static int psp_v11_0_mode1_reset(struct psp_context *psp)

	offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64);

	ret = psp_wait_for(psp, offset, 0x80000000, 0x8000FFFF, false);
	ret = psp_wait_for(psp, offset, MBOX_TOS_READY_FLAG,
			   MBOX_TOS_READY_MASK, false);

	if (ret) {
		DRM_INFO("psp is not working correctly before mode1 reset!\n");
@@ -395,7 +401,8 @@ static int psp_v11_0_mode1_reset(struct psp_context *psp)

	offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_33);

	ret = psp_wait_for(psp, offset, 0x80000000, 0x80000000, false);
	ret = psp_wait_for(psp, offset, MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK,
			   false);

	if (ret) {
		DRM_INFO("psp mode 1 reset failed!\n");
+15 −10
Original line number Diff line number Diff line
@@ -41,8 +41,9 @@ static int psp_v11_0_8_ring_stop(struct psp_context *psp,
		/* there might be handshake issue with hardware which needs delay */
		mdelay(20);
		/* Wait for response flag (bit 31) */
		ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
				   0x80000000, 0x80000000, false);
		ret = psp_wait_for(
			psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
			MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
	} else {
		/* Write the ring destroy command*/
		WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64,
@@ -50,8 +51,9 @@ static int psp_v11_0_8_ring_stop(struct psp_context *psp,
		/* there might be handshake issue with hardware which needs delay */
		mdelay(20);
		/* Wait for response flag (bit 31) */
		ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
				   0x80000000, 0x80000000, false);
		ret = psp_wait_for(
			psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
			MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
	}

	return ret;
@@ -87,13 +89,15 @@ static int psp_v11_0_8_ring_create(struct psp_context *psp,
		mdelay(20);

		/* Wait for response flag (bit 31) in C2PMSG_101 */
		ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
				   0x80000000, 0x8000FFFF, false);
		ret = psp_wait_for(
			psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
			MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);

	} else {
		/* Wait for sOS ready for ring creation */
		ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
				   0x80000000, 0x80000000, false);
		ret = psp_wait_for(
			psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
			MBOX_TOS_READY_FLAG, MBOX_TOS_READY_MASK, false);
		if (ret) {
			DRM_ERROR("Failed to wait for trust OS ready for ring creation\n");
			return ret;
@@ -117,8 +121,9 @@ static int psp_v11_0_8_ring_create(struct psp_context *psp,
		mdelay(20);

		/* Wait for response flag (bit 31) in C2PMSG_64 */
		ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
				   0x80000000, 0x8000FFFF, false);
		ret = psp_wait_for(
			psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
			MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, false);
	}

	return ret;
Loading