drm/amd/display: Add callbacks for DMUB HPD IRQ notifications
authorNicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Thu, 4 Nov 2021 20:52:07 +0000 (16:52 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 9 Nov 2021 22:08:00 +0000 (17:08 -0500)
[Why]
We need HPD IRQ notifications (RX, short pulse) to properly handle
DP MST for DPIA connections.

[How]
A null pointer exception currently occurs when these are received
so add a check to validate that we have a handler installed for
the notification.

Extend the HPD handler to also handle HPD IRQ (RX) since the logic is
the same.

Fixes: e27c41d5b068 ("drm/amd/display: Support for DMUB HPD interrupt handling")

Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
Reviewed-by: Jude Shih <shenshih@amd.com>
Acked-by: Anson Jacob <Anson.Jacob@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c

index 6aafcc1..a7cf7df 100644 (file)
@@ -217,6 +217,7 @@ static const struct drm_format_info *
 amd_get_format_info(const struct drm_mode_fb_cmd2 *cmd);
 
 static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector);
+static void handle_hpd_rx_irq(void *param);
 
 static bool
 is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
@@ -683,8 +684,12 @@ void dmub_hpd_callback(struct amdgpu_device *adev, struct dmub_notification *not
        }
        drm_connector_list_iter_end(&iter);
 
-       if (hpd_aconnector)
-               handle_hpd_irq_helper(hpd_aconnector);
+       if (hpd_aconnector) {
+               if (notify->type == DMUB_NOTIFICATION_HPD)
+                       handle_hpd_irq_helper(hpd_aconnector);
+               else if (notify->type == DMUB_NOTIFICATION_HPD_IRQ)
+                       handle_hpd_rx_irq(hpd_aconnector);
+       }
 }
 
 /**
@@ -760,6 +765,10 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params)
                                DRM_ERROR("DM: notify type %d invalid!", notify.type);
                                continue;
                        }
+                       if (!dm->dmub_callback[notify.type]) {
+                               DRM_DEBUG_DRIVER("DMUB notification skipped, no handler: type=%d\n", notify.type);
+                               continue;
+                       }
                        if (dm->dmub_thread_offload[notify.type] == true) {
                                dmub_hpd_wrk = kzalloc(sizeof(*dmub_hpd_wrk), GFP_ATOMIC);
                                if (!dmub_hpd_wrk) {
@@ -1560,6 +1569,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
                        DRM_ERROR("amdgpu: fail to register dmub hpd callback");
                        goto error;
                }
+               if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_HPD_IRQ, dmub_hpd_callback, true)) {
+                       DRM_ERROR("amdgpu: fail to register dmub hpd callback");
+                       goto error;
+               }
 #endif /* CONFIG_DRM_AMD_DC_DCN */
        }