Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: 7 retries + 50 ms timeout on AUX DEFER

[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.Chalmers@amd.com>
Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Anson Jacob <Anson.Jacob@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Wesley Chalmers and committed by
Alex Deucher
1d5b15f7 d307ce4b

+15 -3
+15 -3
drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
··· 616 616 617 617 #define AUX_MAX_RETRIES 7 618 618 #define AUX_MIN_DEFER_RETRIES 7 619 + #define AUX_MAX_DEFER_TIMEOUT_MS 50 619 620 #define AUX_MAX_I2C_DEFER_RETRIES 7 620 621 #define AUX_MAX_INVALID_REPLY_RETRIES 2 621 622 #define AUX_MAX_TIMEOUT_RETRIES 3 ··· 629 628 bool payload_reply = true; 630 629 enum aux_return_code_type operation_result; 631 630 bool retry_on_defer = false; 631 + struct ddc *ddc_pin = ddc->ddc_pin; 632 + struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; 633 + struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(aux_engine); 634 + uint32_t defer_time_in_ms = 0; 632 635 633 636 int aux_ack_retries = 0, 634 637 aux_defer_retries = 0, ··· 665 660 break; 666 661 667 662 case AUX_TRANSACTION_REPLY_AUX_DEFER: 663 + /* polling_timeout_period is in us */ 664 + defer_time_in_ms += aux110->polling_timeout_period / 1000; 665 + /* fall through */ 668 666 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER: 669 667 retry_on_defer = true; 670 668 fallthrough; 671 669 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK: 672 - if (++aux_defer_retries >= AUX_MIN_DEFER_RETRIES) { 670 + if (++aux_defer_retries >= AUX_MIN_DEFER_RETRIES 671 + && defer_time_in_ms >= AUX_MAX_DEFER_TIMEOUT_MS) { 673 672 goto fail; 674 673 } else { 675 674 if ((*payload->reply == AUX_TRANSACTION_REPLY_AUX_DEFER) || 676 675 (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)) { 677 - if (payload->defer_delay > 1) 676 + if (payload->defer_delay > 1) { 678 677 msleep(payload->defer_delay); 679 - else if (payload->defer_delay <= 1) 678 + defer_time_in_ms += payload->defer_delay; 679 + } else if (payload->defer_delay <= 1) { 680 680 udelay(payload->defer_delay * 1000); 681 + defer_time_in_ms += payload->defer_delay; 682 + } 681 683 } 682 684 } 683 685 break;