From: Wesley Chalmers <wesley.chalm...@amd.com>

[WHY]
DP 2.0 SCR specifies that TX devices must retry at least 7 times when
receiving an AUX DEFER reply from RX. In addition, the specification
states that the TX shall not retry indefinitely, and gives a suggestive
timeout interval of 50ms.

[HOW]
Keep retrying until both 7 or more retries have been made, and the 50ms
interval has passed.

Signed-off-by: Wesley Chalmers <wesley.chalm...@amd.com>
Reviewed-by: Jun Lei <jun....@amd.com>
Acked-by: Anson Jacob <anson.ja...@amd.com>
---
 drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 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 9d5e09b188c2..49cb4e6d6411 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
@@ -616,6 +616,7 @@ int dce_aux_transfer_dmub_raw(struct ddc_service *ddc,
 
 #define AUX_MAX_RETRIES 7
 #define AUX_MIN_DEFER_RETRIES 7
+#define AUX_MAX_DEFER_TIMEOUT_MS 50
 #define AUX_MAX_I2C_DEFER_RETRIES 7
 #define AUX_MAX_INVALID_REPLY_RETRIES 2
 #define AUX_MAX_TIMEOUT_RETRIES 3
@@ -628,6 +629,10 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
        bool payload_reply = true;
        enum aux_return_code_type operation_result;
        bool retry_on_defer = false;
+       struct ddc *ddc_pin = ddc->ddc_pin;
+       struct dce_aux *aux_engine = 
ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
+       struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(aux_engine);
+       uint32_t defer_time_in_ms = 0;
 
        int aux_ack_retries = 0,
                aux_defer_retries = 0,
@@ -660,19 +665,26 @@ bool dce_aux_transfer_with_retries(struct ddc_service 
*ddc,
                        break;
 
                        case AUX_TRANSACTION_REPLY_AUX_DEFER:
+                               /* polling_timeout_period is in us */
+                               defer_time_in_ms += 
aux110->polling_timeout_period / 1000;
+                               /* fall through */
                        case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER:
                                retry_on_defer = true;
                                fallthrough;
                        case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK:
-                               if (++aux_defer_retries >= 
AUX_MIN_DEFER_RETRIES) {
+                               if (++aux_defer_retries >= AUX_MIN_DEFER_RETRIES
+                                               && defer_time_in_ms >= 
AUX_MAX_DEFER_TIMEOUT_MS) {
                                        goto fail;
                                } else {
                                        if ((*payload->reply == 
AUX_TRANSACTION_REPLY_AUX_DEFER) ||
                                                (*payload->reply == 
AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)) {
-                                               if (payload->defer_delay > 1)
+                                               if (payload->defer_delay > 1) {
                                                        
msleep(payload->defer_delay);
-                                               else if (payload->defer_delay 
<= 1)
+                                                       defer_time_in_ms += 
payload->defer_delay;
+                                               } else if (payload->defer_delay 
<= 1) {
                                                        
udelay(payload->defer_delay * 1000);
+                                                       defer_time_in_ms += 
payload->defer_delay;
+                                               }
                                        }
                                }
                                break;
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to