summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
diff options
context:
space:
mode:
authorThomas Lim <Thomas.Lim@amd.com>2019-01-16 15:56:56 -0500
committerAlex Deucher <alexander.deucher@amd.com>2019-03-19 15:04:02 -0500
commit8ae5b1d78d4acbe9755570f26703962877f9108a (patch)
treea97f1a8161bf4ccd579d41bec83129e86f856287 /drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
parent7cef6a120ec4d04c204b2caac226af473b67e410 (diff)
drm/amd/display: Respect aux return values
[Why] The new aux implementation was not up to spec. This caused us to fail DP compliance as well as introduced serious delays during system resume. [How] Make dce_aux_transfer_raw return the operation result Make dce_aux_transfer_with_retries delay with udelay instead of msleep, and only on invalid reply. Also fail on the second invalid reply, third timeout, or first of any other error Convert return values to drm error codes in amdgpu_dm As the two aux transfer functions are now noticeably different, change the names to better reflect their functionality and document. There was one last call to dc_link_aux_transfer that should have retries, fix that Signed-off-by: David Francis <David.Francis@amd.com> Signed-off-by: Thomas Lim <Thomas.Lim@amd.com> Reviewed-by: David Francis <David.Francis@amd.com> Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> Acked-by: Eric Yang <eric.yang2@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c')
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index c4ea3a91f17a..6e205ee36ac3 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -84,6 +84,7 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
{
ssize_t result = 0;
struct aux_payload payload;
+ enum aux_channel_operation_result operation_result;
if (WARN_ON(msg->size > 16))
return -E2BIG;
@@ -97,13 +98,27 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
payload.mot = (msg->request & DP_AUX_I2C_MOT) != 0;
payload.defer_delay = 0;
- result = dc_link_aux_transfer(TO_DM_AUX(aux)->ddc_service, &payload);
+ result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload,
+ &operation_result);
if (payload.write)
result = msg->size;
- if (result < 0) /* DC doesn't know about kernel error codes */
- result = -EIO;
+ if (result < 0)
+ switch (operation_result) {
+ case AUX_CHANNEL_OPERATION_SUCCEEDED:
+ break;
+ case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
+ case AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN:
+ result = -EIO;
+ break;
+ case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
+ result = -EBUSY;
+ break;
+ case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
+ result = -ETIMEDOUT;
+ break;
+ }
return result;
}