Commit 65924ec6 authored by Wayne Lin's avatar Wayne Lin Committed by Alex Deucher
Browse files

drm/amd/display: Fix wrong handling for AUX_DEFER case



[Why]
We incorrectly ack all bytes get written when the reply actually is defer.
When it's defer, means sink is not ready for the request. We should
retry the request.

[How]
Only reply all data get written when receive I2C_ACK|AUX_ACK. Otherwise,
reply the number of actual written bytes received from the sink.
Add some messages to facilitate debugging as well.

Fixes: ad6756b4 ("drm/amd/display: Shift dc link aux to aux_payload")
Cc: Mario Limonciello <mario.limonciello@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: default avatarRay Wu <ray.wu@amd.com>
Signed-off-by: default avatarWayne Lin <Wayne.Lin@amd.com>
Signed-off-by: default avatarRay Wu <ray.wu@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 3637e457)
Cc: stable@vger.kernel.org
parent 3924f45d
Loading
Loading
Loading
Loading
+24 −4
Original line number Diff line number Diff line
@@ -51,6 +51,9 @@

#define PEAK_FACTOR_X1000 1006

/*
 * This function handles both native AUX and I2C-Over-AUX transactions.
 */
static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
				  struct drm_dp_aux_msg *msg)
{
@@ -87,15 +90,25 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
	if (adev->dm.aux_hpd_discon_quirk) {
		if (msg->address == DP_SIDEBAND_MSG_DOWN_REQ_BASE &&
			operation_result == AUX_RET_ERROR_HPD_DISCON) {
			result = 0;
			result = msg->size;
			operation_result = AUX_RET_SUCCESS;
		}
	}

	if (payload.write && result >= 0)
	/*
	 * result equals to 0 includes the cases of AUX_DEFER/I2C_DEFER
	 */
	if (payload.write && result >= 0) {
		if (result) {
			/*one byte indicating partially written bytes. Force 0 to retry*/
			drm_info(adev_to_drm(adev), "amdgpu: AUX partially written\n");
			result = 0;
		} else if (!payload.reply[0])
			/*I2C_ACK|AUX_ACK*/
			result = msg->size;
	}

	if (result < 0)
	if (result < 0) {
		switch (operation_result) {
		case AUX_RET_SUCCESS:
			break;
@@ -114,6 +127,13 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
			break;
		}

		drm_info(adev_to_drm(adev), "amdgpu: DP AUX transfer fail:%d\n", operation_result);
	}

	if (payload.reply[0])
		drm_info(adev_to_drm(adev), "amdgpu: AUX reply command not ACK: 0x%02x.",
			payload.reply[0]);

	return result;
}