|
|
@@ -178,8 +178,8 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
|
|
|
unsigned int offset, void *buffer, size_t size)
|
|
|
{
|
|
|
struct drm_dp_aux_msg msg;
|
|
|
- unsigned int retry;
|
|
|
- int err = 0;
|
|
|
+ unsigned int retry, native_reply;
|
|
|
+ int err = 0, ret = 0;
|
|
|
|
|
|
memset(&msg, 0, sizeof(msg));
|
|
|
msg.address = offset;
|
|
|
@@ -196,37 +196,39 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
|
|
|
* sufficient, bump to 32 which makes Dell 4k monitors happier.
|
|
|
*/
|
|
|
for (retry = 0; retry < 32; retry++) {
|
|
|
- if (err != 0 && err != -ETIMEDOUT) {
|
|
|
+ if (ret != 0 && ret != -ETIMEDOUT) {
|
|
|
usleep_range(AUX_RETRY_INTERVAL,
|
|
|
AUX_RETRY_INTERVAL + 100);
|
|
|
}
|
|
|
|
|
|
- err = aux->transfer(aux, &msg);
|
|
|
- if (err < 0) {
|
|
|
- if (err == -EBUSY)
|
|
|
- continue;
|
|
|
-
|
|
|
- goto unlock;
|
|
|
- }
|
|
|
+ ret = aux->transfer(aux, &msg);
|
|
|
|
|
|
- switch (msg.reply & DP_AUX_NATIVE_REPLY_MASK) {
|
|
|
- case DP_AUX_NATIVE_REPLY_ACK:
|
|
|
- if (err < size)
|
|
|
- err = -EPROTO;
|
|
|
- goto unlock;
|
|
|
+ if (ret > 0) {
|
|
|
+ native_reply = msg.reply & DP_AUX_NATIVE_REPLY_MASK;
|
|
|
+ if (native_reply == DP_AUX_NATIVE_REPLY_ACK) {
|
|
|
+ if (ret == size)
|
|
|
+ goto unlock;
|
|
|
|
|
|
- case DP_AUX_NATIVE_REPLY_NACK:
|
|
|
- err = -EIO;
|
|
|
- goto unlock;
|
|
|
+ ret = -EPROTO;
|
|
|
+ } else
|
|
|
+ ret = -EIO;
|
|
|
}
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We want the error we return to be the error we received on
|
|
|
+ * the first transaction, since we may get a different error the
|
|
|
+ * next time we retry
|
|
|
+ */
|
|
|
+ if (!err)
|
|
|
+ err = ret;
|
|
|
}
|
|
|
|
|
|
DRM_DEBUG_KMS("too many retries, giving up\n");
|
|
|
- err = -EIO;
|
|
|
+ ret = err;
|
|
|
|
|
|
unlock:
|
|
|
mutex_unlock(&aux->hw_mutex);
|
|
|
- return err;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
/**
|