diff options
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 41 |
2 files changed, 36 insertions, 8 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 5bbf97e26d87..ab61aaa887bb 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -620,7 +620,8 @@ enum radeon_dynpm_state { | |||
| 620 | DYNPM_STATE_DISABLED, | 620 | DYNPM_STATE_DISABLED, |
| 621 | DYNPM_STATE_MINIMUM, | 621 | DYNPM_STATE_MINIMUM, |
| 622 | DYNPM_STATE_PAUSED, | 622 | DYNPM_STATE_PAUSED, |
| 623 | DYNPM_STATE_ACTIVE | 623 | DYNPM_STATE_ACTIVE, |
| 624 | DYNPM_STATE_SUSPENDED, | ||
| 624 | }; | 625 | }; |
| 625 | enum radeon_dynpm_action { | 626 | enum radeon_dynpm_action { |
| 626 | DYNPM_ACTION_NONE, | 627 | DYNPM_ACTION_NONE, |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 63f679a04b25..115d26b762cc 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
| @@ -397,13 +397,20 @@ static ssize_t radeon_set_pm_method(struct device *dev, | |||
| 397 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT; | 397 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT; |
| 398 | mutex_unlock(&rdev->pm.mutex); | 398 | mutex_unlock(&rdev->pm.mutex); |
| 399 | } else if (strncmp("profile", buf, strlen("profile")) == 0) { | 399 | } else if (strncmp("profile", buf, strlen("profile")) == 0) { |
| 400 | bool flush_wq = false; | ||
| 401 | |||
| 400 | mutex_lock(&rdev->pm.mutex); | 402 | mutex_lock(&rdev->pm.mutex); |
| 401 | rdev->pm.pm_method = PM_METHOD_PROFILE; | 403 | if (rdev->pm.pm_method == PM_METHOD_DYNPM) { |
| 404 | cancel_delayed_work(&rdev->pm.dynpm_idle_work); | ||
| 405 | flush_wq = true; | ||
| 406 | } | ||
| 402 | /* disable dynpm */ | 407 | /* disable dynpm */ |
| 403 | rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; | 408 | rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; |
| 404 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; | 409 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_NONE; |
| 405 | cancel_delayed_work(&rdev->pm.dynpm_idle_work); | 410 | rdev->pm.pm_method = PM_METHOD_PROFILE; |
| 406 | mutex_unlock(&rdev->pm.mutex); | 411 | mutex_unlock(&rdev->pm.mutex); |
| 412 | if (flush_wq) | ||
| 413 | flush_workqueue(rdev->wq); | ||
| 407 | } else { | 414 | } else { |
| 408 | DRM_ERROR("invalid power method!\n"); | 415 | DRM_ERROR("invalid power method!\n"); |
| 409 | goto fail; | 416 | goto fail; |
| @@ -418,9 +425,18 @@ static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon | |||
| 418 | 425 | ||
| 419 | void radeon_pm_suspend(struct radeon_device *rdev) | 426 | void radeon_pm_suspend(struct radeon_device *rdev) |
| 420 | { | 427 | { |
| 428 | bool flush_wq = false; | ||
| 429 | |||
| 421 | mutex_lock(&rdev->pm.mutex); | 430 | mutex_lock(&rdev->pm.mutex); |
| 422 | cancel_delayed_work(&rdev->pm.dynpm_idle_work); | 431 | if (rdev->pm.pm_method == PM_METHOD_DYNPM) { |
| 432 | cancel_delayed_work(&rdev->pm.dynpm_idle_work); | ||
| 433 | if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE) | ||
| 434 | rdev->pm.dynpm_state = DYNPM_STATE_SUSPENDED; | ||
| 435 | flush_wq = true; | ||
| 436 | } | ||
| 423 | mutex_unlock(&rdev->pm.mutex); | 437 | mutex_unlock(&rdev->pm.mutex); |
| 438 | if (flush_wq) | ||
| 439 | flush_workqueue(rdev->wq); | ||
| 424 | } | 440 | } |
| 425 | 441 | ||
| 426 | void radeon_pm_resume(struct radeon_device *rdev) | 442 | void radeon_pm_resume(struct radeon_device *rdev) |
| @@ -432,6 +448,12 @@ void radeon_pm_resume(struct radeon_device *rdev) | |||
| 432 | rdev->pm.current_sclk = rdev->clock.default_sclk; | 448 | rdev->pm.current_sclk = rdev->clock.default_sclk; |
| 433 | rdev->pm.current_mclk = rdev->clock.default_mclk; | 449 | rdev->pm.current_mclk = rdev->clock.default_mclk; |
| 434 | rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; | 450 | rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage; |
| 451 | if (rdev->pm.pm_method == PM_METHOD_DYNPM | ||
| 452 | && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) { | ||
| 453 | rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE; | ||
| 454 | queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work, | ||
| 455 | msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); | ||
| 456 | } | ||
| 435 | mutex_unlock(&rdev->pm.mutex); | 457 | mutex_unlock(&rdev->pm.mutex); |
| 436 | radeon_pm_compute_clocks(rdev); | 458 | radeon_pm_compute_clocks(rdev); |
| 437 | } | 459 | } |
| @@ -486,6 +508,8 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
| 486 | void radeon_pm_fini(struct radeon_device *rdev) | 508 | void radeon_pm_fini(struct radeon_device *rdev) |
| 487 | { | 509 | { |
| 488 | if (rdev->pm.num_power_states > 1) { | 510 | if (rdev->pm.num_power_states > 1) { |
| 511 | bool flush_wq = false; | ||
| 512 | |||
| 489 | mutex_lock(&rdev->pm.mutex); | 513 | mutex_lock(&rdev->pm.mutex); |
| 490 | if (rdev->pm.pm_method == PM_METHOD_PROFILE) { | 514 | if (rdev->pm.pm_method == PM_METHOD_PROFILE) { |
| 491 | rdev->pm.profile = PM_PROFILE_DEFAULT; | 515 | rdev->pm.profile = PM_PROFILE_DEFAULT; |
| @@ -493,13 +517,16 @@ void radeon_pm_fini(struct radeon_device *rdev) | |||
| 493 | radeon_pm_set_clocks(rdev); | 517 | radeon_pm_set_clocks(rdev); |
| 494 | } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) { | 518 | } else if (rdev->pm.pm_method == PM_METHOD_DYNPM) { |
| 495 | /* cancel work */ | 519 | /* cancel work */ |
| 496 | cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work); | 520 | cancel_delayed_work(&rdev->pm.dynpm_idle_work); |
| 521 | flush_wq = true; | ||
| 497 | /* reset default clocks */ | 522 | /* reset default clocks */ |
| 498 | rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; | 523 | rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; |
| 499 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT; | 524 | rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT; |
| 500 | radeon_pm_set_clocks(rdev); | 525 | radeon_pm_set_clocks(rdev); |
| 501 | } | 526 | } |
| 502 | mutex_unlock(&rdev->pm.mutex); | 527 | mutex_unlock(&rdev->pm.mutex); |
| 528 | if (flush_wq) | ||
| 529 | flush_workqueue(rdev->wq); | ||
| 503 | 530 | ||
| 504 | device_remove_file(rdev->dev, &dev_attr_power_profile); | 531 | device_remove_file(rdev->dev, &dev_attr_power_profile); |
| 505 | device_remove_file(rdev->dev, &dev_attr_power_method); | 532 | device_remove_file(rdev->dev, &dev_attr_power_method); |
| @@ -720,12 +747,12 @@ static void radeon_dynpm_idle_work_handler(struct work_struct *work) | |||
| 720 | radeon_pm_get_dynpm_state(rdev); | 747 | radeon_pm_get_dynpm_state(rdev); |
| 721 | radeon_pm_set_clocks(rdev); | 748 | radeon_pm_set_clocks(rdev); |
| 722 | } | 749 | } |
| 750 | |||
| 751 | queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work, | ||
| 752 | msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); | ||
| 723 | } | 753 | } |
| 724 | mutex_unlock(&rdev->pm.mutex); | 754 | mutex_unlock(&rdev->pm.mutex); |
| 725 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); | 755 | ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); |
| 726 | |||
| 727 | queue_delayed_work(rdev->wq, &rdev->pm.dynpm_idle_work, | ||
| 728 | msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); | ||
| 729 | } | 756 | } |
| 730 | 757 | ||
| 731 | /* | 758 | /* |
