radeon: Take drm struct_mutex over reclocking
authorMatthew Garrett <mjg@redhat.com>
Mon, 26 Apr 2010 19:57:01 +0000 (15:57 -0400)
committerDave Airlie <airlied@redhat.com>
Tue, 18 May 2010 08:21:19 +0000 (18:21 +1000)
We need to block the drm core from doing anything that may touch our vram
during reclock, so take the drm mutex for the duration.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/radeon/radeon_pm.c

index da35bd7..c9390ea 100644 (file)
@@ -131,6 +131,7 @@ static ssize_t radeon_set_power_state_static(struct device *dev,
                return count;
        }
 
+       mutex_lock(&rdev->ddev->struct_mutex);
        mutex_lock(&rdev->pm.mutex);
        if ((ps >= 0) && (ps < rdev->pm.num_power_states) &&
            (cm >= 0) && (cm < rdev->pm.power_state[ps].num_clock_modes)) {
@@ -148,6 +149,7 @@ static ssize_t radeon_set_power_state_static(struct device *dev,
        } else
                DRM_ERROR("Invalid power state: %d.%d\n\n", ps, cm);
        mutex_unlock(&rdev->pm.mutex);
+       mutex_unlock(&rdev->ddev->struct_mutex);
 
        return count;
 }
@@ -184,11 +186,13 @@ static ssize_t radeon_set_dynpm(struct device *dev,
        } else if (tmp == 1) {
                if (rdev->pm.num_power_states > 1) {
                        /* enable dynpm */
+                       mutex_lock(&rdev->ddev->struct_mutex);
                        mutex_lock(&rdev->pm.mutex);
                        rdev->pm.state = PM_STATE_PAUSED;
                        rdev->pm.planned_action = PM_ACTION_DEFAULT;
                        radeon_get_power_state(rdev, rdev->pm.planned_action);
                        mutex_unlock(&rdev->pm.mutex);
+                       mutex_unlock(&rdev->ddev->struct_mutex);
                        /* update power mode info */
                        radeon_pm_compute_clocks(rdev);
                        DRM_INFO("radeon: dynamic power management enabled\n");
@@ -311,9 +315,11 @@ void radeon_pm_fini(struct radeon_device *rdev)
                   (rdev->pm.current_clock_mode_index != 0)) {
                rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index;
                rdev->pm.requested_clock_mode_index = 0;
+               mutex_lock(&rdev->ddev->struct_mutex);
                mutex_lock(&rdev->pm.mutex);
                radeon_pm_set_clocks(rdev, true);
                mutex_unlock(&rdev->pm.mutex);
+               mutex_unlock(&rdev->ddev->struct_mutex);
        }
 
        device_remove_file(rdev->dev, &dev_attr_power_state);
@@ -332,6 +338,7 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev)
        if (rdev->pm.state == PM_STATE_DISABLED)
                return;
 
+       mutex_lock(&rdev->ddev->struct_mutex);
        mutex_lock(&rdev->pm.mutex);
 
        rdev->pm.active_crtcs = 0;
@@ -382,6 +389,7 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev)
        }
 
        mutex_unlock(&rdev->pm.mutex);
+       mutex_unlock(&rdev->ddev->struct_mutex);
 }
 
 bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish)
@@ -455,6 +463,7 @@ static void radeon_pm_idle_work_handler(struct work_struct *work)
        rdev = container_of(work, struct radeon_device,
                                pm.idle_work.work);
 
+       mutex_lock(&rdev->ddev->struct_mutex);
        mutex_lock(&rdev->pm.mutex);
        if (rdev->pm.state == PM_STATE_ACTIVE) {
                unsigned long irq_flags;
@@ -499,6 +508,7 @@ static void radeon_pm_idle_work_handler(struct work_struct *work)
                }
        }
        mutex_unlock(&rdev->pm.mutex);
+       mutex_unlock(&rdev->ddev->struct_mutex);
 
        queue_delayed_work(rdev->wq, &rdev->pm.idle_work,
                                        msecs_to_jiffies(RADEON_IDLE_LOOP_MS));