On 7/11/2022 17:10, Rodrigo Siqueira wrote:
From: Fangzhi Zuo Jerry.Zuo@amd.com
[why] The first MST sideband message returns AUX_RET_ERROR_HPD_DISCON on a certain Intel platform. Aux transaction is considered a failure if HPD unexpectedly pulled low. The actual aux transaction success in such case, hence do not return an error. Several Dell Intel-based Precision systems had this issue, for example, Precision 3260 and 3460.
[how] Not returning error when AUX_RET_ERROR_HPD_DISCON detected on the first sideband message.
Changes since v1:
- Add two missing products
Cc: Harry Wentland harry.wentland@amd.com Cc: Mario Limonciello mario.limonciello@amd.com Cc: Qian Fu Qian.Fu@dell.com Cc: stable@vger.kernel.org Signed-off-by: Fangzhi Zuo Jerry.Zuo@amd.com
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 29 +++++++++++++++++++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 8 +++++ .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 17 +++++++++++ 3 files changed, 54 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index de1c139ae279..3c7f6920f71f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -72,6 +72,7 @@ #include <linux/pci.h> #include <linux/firmware.h> #include <linux/component.h> +#include <linux/dmi.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_uapi.h> @@ -1400,6 +1401,31 @@ static bool dm_should_disable_stutter(struct pci_dev *pdev) return false; } +static const struct dmi_system_id hpd_disconnect_quirk_table[] = {
- {
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3660"),
DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3260"),
DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3460"),
},
- },
- {}
+};
This still isn't formulated correctly unfortunately to match all 3 systems. They need to be their own DMI matches. It should be like this:
static const struct dmi_system_id hpd_disconnect_quirk_table[] = { { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3660"), }, }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3260"), }, }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3460"), }, }, {} };
+void retrieve_dmi_info(struct amdgpu_display_manager *dm) +{
- const struct dmi_system_id *dmi_id;
- dm->aux_hpd_discon_quirk = false;
- dmi_id = dmi_first_match(hpd_disconnect_quirk_table);
- if (dmi_id) {
dm->aux_hpd_discon_quirk = true;
DRM_INFO("aux_hpd_discon_quirk attached\n");
- }
+}
- static int amdgpu_dm_init(struct amdgpu_device *adev) { struct dc_init_data init_data;
@@ -1528,6 +1554,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) init_data.flags.enable_mipi_converter_optimization = true; INIT_LIST_HEAD(&adev->dm.da_list);
- retrieve_dmi_info(&adev->dm);
- /* Display Core create. */ adev->dm.dc = dc_create(&init_data);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index e04e6b3f609f..33d66d4897dc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -547,6 +547,14 @@ struct amdgpu_display_manager { * last successfully applied backlight values. */ u32 actual_brightness[AMDGPU_DM_MAX_NUM_EDP];
- /**
* @aux_hpd_discon_quirk:
*
* quirk for hpd discon while aux is on-going.
* occurred on certain intel platform
*/
- bool aux_hpd_discon_quirk; };
enum dsc_clock_force_state { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 8237029cedf5..168d5676b657 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -56,6 +56,8 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, ssize_t result = 0; struct aux_payload payload; enum aux_return_code_type operation_result;
- struct amdgpu_device *adev;
- struct ddc_service *ddc;
if (WARN_ON(msg->size > 16)) return -E2BIG; @@ -74,6 +76,21 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload, &operation_result);
- /*
* w/a on certain intel platform where hpd is unexpected to pull low during
* 1st sideband message transaction by return AUX_RET_ERROR_HPD_DISCON
* aux transaction is succuess in such case, therefore bypass the error
*/
- ddc = TO_DM_AUX(aux)->ddc_service;
- adev = ddc->ctx->driver_context;
- if (adev->dm.aux_hpd_discon_quirk) {
if (msg->address == DP_SIDEBAND_MSG_DOWN_REQ_BASE &&
operation_result == AUX_RET_ERROR_HPD_DISCON) {
result = 0;
operation_result = AUX_RET_SUCCESS;
}
- }
- if (payload.write && result >= 0) result = msg->size;