From: George Shen <[email protected]>

[Why]
When a timeout occurs after a DEFER, some devices require more retries
than in the case of a regular timeout.

[How]
In a timeout occurrence, check whether a DEFER has occurred before the
timeout and retry MAX_DEFER_RETRIES retries times instead of
MAX_TIMEOUT_RETRIES.

Signed-off-by: George Shen <[email protected]>
Reviewed-by: Tony Cheng <[email protected]>
Acked-by: Abdoulaye Berthe <[email protected]>
Acked-by: Leo Li <[email protected]>
---
 drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 32 ++++++++++++++------
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c 
b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
index f7626cd70ec8..191b68b8163a 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
@@ -611,6 +611,8 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
        uint8_t reply;
        bool payload_reply = true;
        enum aux_channel_operation_result operation_result;
+       bool retry_on_defer = false;
+
        int aux_ack_retries = 0,
                aux_defer_retries = 0,
                aux_i2c_defer_retries = 0,
@@ -641,8 +643,9 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
                        break;
 
                        case AUX_TRANSACTION_REPLY_AUX_DEFER:
-                       case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK:
                        case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER:
+                               retry_on_defer = true;
+                       case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK:
                                if (++aux_defer_retries >= 
AUX_MAX_DEFER_RETRIES) {
                                        goto fail;
                                } else {
@@ -675,15 +678,24 @@ bool dce_aux_transfer_with_retries(struct ddc_service 
*ddc,
                        break;
 
                case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
-                       if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES)
-                               goto fail;
-                       else {
-                               /*
-                                * DP 1.4, 2.8.2:  AUX Transaction 
Response/Reply Timeouts
-                                * According to the DP spec there should be 3 
retries total
-                                * with a 400us wait inbetween each. Hardware 
already waits
-                                * for 550us therefore no wait is required here.
-                                */
+                       // Check whether a DEFER had occurred before the 
timeout.
+                       // If so, treat timeout as a DEFER.
+                       if (retry_on_defer) {
+                               if (++aux_defer_retries >= 
AUX_MAX_DEFER_RETRIES)
+                                       goto fail;
+                               else if (payload->defer_delay > 0)
+                                       msleep(payload->defer_delay);
+                       } else {
+                               if (++aux_timeout_retries >= 
AUX_MAX_TIMEOUT_RETRIES)
+                                       goto fail;
+                               else {
+                                       /*
+                                        * DP 1.4, 2.8.2:  AUX Transaction 
Response/Reply Timeouts
+                                        * According to the DP spec there 
should be 3 retries total
+                                        * with a 400us wait inbetween each. 
Hardware already waits
+                                        * for 550us therefore no wait is 
required here.
+                                        */
+                               }
                        }
                        break;
 
-- 
2.24.0

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to