drm/radeon/pm: don't allow debugfs/sysfs access when PX card is off (v2)
When the PX card is off don't try and access it. Avoid hw access to the card while it's off (e.g., reading back invalid temperature). v2: be less strict bug: https://bugzilla.kernel.org/show_bug.cgi?id=76321 Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Cc: stable@vger.kernel.org Signed-off-by: Christian König <christian.koenig@amd.com>
This commit is contained in:
parent
24f47acc78
commit
4f2f203976
1 changed files with 41 additions and 1 deletions
|
@ -361,6 +361,11 @@ static ssize_t radeon_set_pm_profile(struct device *dev,
|
|||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct radeon_device *rdev = ddev->dev_private;
|
||||
|
||||
/* Can't set profile when the card is off */
|
||||
if ((rdev->flags & RADEON_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&rdev->pm.mutex);
|
||||
if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
|
||||
if (strncmp("default", buf, strlen("default")) == 0)
|
||||
|
@ -409,6 +414,13 @@ static ssize_t radeon_set_pm_method(struct device *dev,
|
|||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct radeon_device *rdev = ddev->dev_private;
|
||||
|
||||
/* Can't set method when the card is off */
|
||||
if ((rdev->flags & RADEON_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON)) {
|
||||
count = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* we don't support the legacy modes with dpm */
|
||||
if (rdev->pm.pm_method == PM_METHOD_DPM) {
|
||||
count = -EINVAL;
|
||||
|
@ -446,6 +458,10 @@ static ssize_t radeon_get_dpm_state(struct device *dev,
|
|||
struct radeon_device *rdev = ddev->dev_private;
|
||||
enum radeon_pm_state_type pm = rdev->pm.dpm.user_state;
|
||||
|
||||
if ((rdev->flags & RADEON_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
|
||||
return snprintf(buf, PAGE_SIZE, "off\n");
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
(pm == POWER_STATE_TYPE_BATTERY) ? "battery" :
|
||||
(pm == POWER_STATE_TYPE_BALANCED) ? "balanced" : "performance");
|
||||
|
@ -459,6 +475,11 @@ static ssize_t radeon_set_dpm_state(struct device *dev,
|
|||
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||
struct radeon_device *rdev = ddev->dev_private;
|
||||
|
||||
/* Can't set dpm state when the card is off */
|
||||
if ((rdev->flags & RADEON_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&rdev->pm.mutex);
|
||||
if (strncmp("battery", buf, strlen("battery")) == 0)
|
||||
rdev->pm.dpm.user_state = POWER_STATE_TYPE_BATTERY;
|
||||
|
@ -485,6 +506,10 @@ static ssize_t radeon_get_dpm_forced_performance_level(struct device *dev,
|
|||
struct radeon_device *rdev = ddev->dev_private;
|
||||
enum radeon_dpm_forced_level level = rdev->pm.dpm.forced_level;
|
||||
|
||||
if ((rdev->flags & RADEON_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
|
||||
return snprintf(buf, PAGE_SIZE, "off\n");
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
(level == RADEON_DPM_FORCED_LEVEL_AUTO) ? "auto" :
|
||||
(level == RADEON_DPM_FORCED_LEVEL_LOW) ? "low" : "high");
|
||||
|
@ -500,6 +525,11 @@ static ssize_t radeon_set_dpm_forced_performance_level(struct device *dev,
|
|||
enum radeon_dpm_forced_level level;
|
||||
int ret = 0;
|
||||
|
||||
/* Can't force performance level when the card is off */
|
||||
if ((rdev->flags & RADEON_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&rdev->pm.mutex);
|
||||
if (strncmp("low", buf, strlen("low")) == 0) {
|
||||
level = RADEON_DPM_FORCED_LEVEL_LOW;
|
||||
|
@ -538,8 +568,14 @@ static ssize_t radeon_hwmon_show_temp(struct device *dev,
|
|||
char *buf)
|
||||
{
|
||||
struct radeon_device *rdev = dev_get_drvdata(dev);
|
||||
struct drm_device *ddev = rdev->ddev;
|
||||
int temp;
|
||||
|
||||
/* Can't get temperature when the card is off */
|
||||
if ((rdev->flags & RADEON_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON))
|
||||
return -EINVAL;
|
||||
|
||||
if (rdev->asic->pm.get_temperature)
|
||||
temp = radeon_get_temperature(rdev);
|
||||
else
|
||||
|
@ -1614,8 +1650,12 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data)
|
|||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct drm_device *ddev = rdev->ddev;
|
||||
|
||||
if (rdev->pm.dpm_enabled) {
|
||||
if ((rdev->flags & RADEON_IS_PX) &&
|
||||
(ddev->switch_power_state != DRM_SWITCH_POWER_ON)) {
|
||||
seq_printf(m, "PX asic powered off\n");
|
||||
} else if (rdev->pm.dpm_enabled) {
|
||||
mutex_lock(&rdev->pm.mutex);
|
||||
if (rdev->asic->dpm.debugfs_print_current_performance_level)
|
||||
radeon_dpm_debugfs_print_current_performance_level(rdev, m);
|
||||
|
|
Loading…
Reference in a new issue