drm/radeon/pm: don't walk the crtc list before it has been initialized (v2)
authorAlex Deucher <alexdeucher@gmail.com>
Tue, 15 Apr 2014 16:44:33 +0000 (12:44 -0400)
committerChristian König <christian.koenig@amd.com>
Tue, 22 Apr 2014 14:51:19 +0000 (16:51 +0200)
Avoids a crash in certain cases when thermal irqs are generated
before the display structures have been initialized.

v2: fix the vblank and vrefresh helpers as well

bug:
https://bugzilla.kernel.org/show_bug.cgi?id=73931

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
drivers/gpu/drm/radeon/r600_dpm.c
drivers/gpu/drm/radeon/radeon_pm.c

index cbf7e3269f84882d1352a44ea402fa5dc4cbba7c..9c61b74ef4415cbf1f7bce501b268662d80da8de 100644 (file)
@@ -158,16 +158,18 @@ u32 r600_dpm_get_vblank_time(struct radeon_device *rdev)
        u32 line_time_us, vblank_lines;
        u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */
 
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               radeon_crtc = to_radeon_crtc(crtc);
-               if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
-                       line_time_us = (radeon_crtc->hw_mode.crtc_htotal * 1000) /
-                               radeon_crtc->hw_mode.clock;
-                       vblank_lines = radeon_crtc->hw_mode.crtc_vblank_end -
-                               radeon_crtc->hw_mode.crtc_vdisplay +
-                               (radeon_crtc->v_border * 2);
-                       vblank_time_us = vblank_lines * line_time_us;
-                       break;
+       if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
+               list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+                       radeon_crtc = to_radeon_crtc(crtc);
+                       if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
+                               line_time_us = (radeon_crtc->hw_mode.crtc_htotal * 1000) /
+                                       radeon_crtc->hw_mode.clock;
+                               vblank_lines = radeon_crtc->hw_mode.crtc_vblank_end -
+                                       radeon_crtc->hw_mode.crtc_vdisplay +
+                                       (radeon_crtc->v_border * 2);
+                               vblank_time_us = vblank_lines * line_time_us;
+                               break;
+                       }
                }
        }
 
@@ -181,14 +183,15 @@ u32 r600_dpm_get_vrefresh(struct radeon_device *rdev)
        struct radeon_crtc *radeon_crtc;
        u32 vrefresh = 0;
 
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               radeon_crtc = to_radeon_crtc(crtc);
-               if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
-                       vrefresh = radeon_crtc->hw_mode.vrefresh;
-                       break;
+       if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
+               list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+                       radeon_crtc = to_radeon_crtc(crtc);
+                       if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
+                               vrefresh = radeon_crtc->hw_mode.vrefresh;
+                               break;
+                       }
                }
        }
-
        return vrefresh;
 }
 
index d79895aebc591278da9328216de0a7e871aaae36..6fac8efe8340e2e99f83965201bab056de2997de 100644 (file)
@@ -1406,12 +1406,14 @@ static void radeon_pm_compute_clocks_old(struct radeon_device *rdev)
 
        rdev->pm.active_crtcs = 0;
        rdev->pm.active_crtc_count = 0;
-       list_for_each_entry(crtc,
-               &ddev->mode_config.crtc_list, head) {
-               radeon_crtc = to_radeon_crtc(crtc);
-               if (radeon_crtc->enabled) {
-                       rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id);
-                       rdev->pm.active_crtc_count++;
+       if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
+               list_for_each_entry(crtc,
+                                   &ddev->mode_config.crtc_list, head) {
+                       radeon_crtc = to_radeon_crtc(crtc);
+                       if (radeon_crtc->enabled) {
+                               rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id);
+                               rdev->pm.active_crtc_count++;
+                       }
                }
        }
 
@@ -1478,12 +1480,14 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
        /* update active crtc counts */
        rdev->pm.dpm.new_active_crtcs = 0;
        rdev->pm.dpm.new_active_crtc_count = 0;
-       list_for_each_entry(crtc,
-               &ddev->mode_config.crtc_list, head) {
-               radeon_crtc = to_radeon_crtc(crtc);
-               if (crtc->enabled) {
-                       rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id);
-                       rdev->pm.dpm.new_active_crtc_count++;
+       if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
+               list_for_each_entry(crtc,
+                                   &ddev->mode_config.crtc_list, head) {
+                       radeon_crtc = to_radeon_crtc(crtc);
+                       if (crtc->enabled) {
+                               rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id);
+                               rdev->pm.dpm.new_active_crtc_count++;
+                       }
                }
        }