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;
* 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;
}
/**