Commit 0975b162 authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie

drm/radeon/kms: dynamically allocate power state space

We previously used a static array, but some new systems
had more states then we had array space, so dynamically
allocate space based on the number of states in the vbios.

Fixes:
https://bugs.freedesktop.org/show_bug.cgi?id=33851Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Cc: stable@kernel.org
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 87364760
...@@ -812,8 +812,7 @@ struct radeon_pm { ...@@ -812,8 +812,7 @@ struct radeon_pm {
fixed20_12 sclk; fixed20_12 sclk;
fixed20_12 mclk; fixed20_12 mclk;
fixed20_12 needed_bandwidth; fixed20_12 needed_bandwidth;
/* XXX: use a define for num power modes */ struct radeon_power_state *power_state;
struct radeon_power_state power_state[8];
/* number of valid power states */ /* number of valid power states */
int num_power_states; int num_power_states;
int current_power_state_index; int current_power_state_index;
......
...@@ -1977,6 +1977,9 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) ...@@ -1977,6 +1977,9 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
num_modes = power_info->info.ucNumOfPowerModeEntries; num_modes = power_info->info.ucNumOfPowerModeEntries;
if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK) if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK; num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * num_modes, GFP_KERNEL);
if (!rdev->pm.power_state)
return state_index;
/* last mode is usually default, array is low to high */ /* last mode is usually default, array is low to high */
for (i = 0; i < num_modes; i++) { for (i = 0; i < num_modes; i++) {
rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
...@@ -2328,6 +2331,10 @@ static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev) ...@@ -2328,6 +2331,10 @@ static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev)
power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController);
rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) *
power_info->pplib.ucNumStates, GFP_KERNEL);
if (!rdev->pm.power_state)
return state_index;
/* first mode is usually default, followed by low to high */ /* first mode is usually default, followed by low to high */
for (i = 0; i < power_info->pplib.ucNumStates; i++) { for (i = 0; i < power_info->pplib.ucNumStates; i++) {
mode_index = 0; mode_index = 0;
...@@ -2408,6 +2415,10 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) ...@@ -2408,6 +2415,10 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev)
non_clock_info_array = (struct NonClockInfoArray *) non_clock_info_array = (struct NonClockInfoArray *)
(mode_info->atom_context->bios + data_offset + (mode_info->atom_context->bios + data_offset +
power_info->pplib.usNonClockInfoArrayOffset); power_info->pplib.usNonClockInfoArrayOffset);
rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) *
state_array->ucNumEntries, GFP_KERNEL);
if (!rdev->pm.power_state)
return state_index;
for (i = 0; i < state_array->ucNumEntries; i++) { for (i = 0; i < state_array->ucNumEntries; i++) {
mode_index = 0; mode_index = 0;
power_state = (union pplib_power_state *)&state_array->states[i]; power_state = (union pplib_power_state *)&state_array->states[i];
...@@ -2481,19 +2492,22 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) ...@@ -2481,19 +2492,22 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
break; break;
} }
} else { } else {
/* add the default mode */ rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state), GFP_KERNEL);
rdev->pm.power_state[state_index].type = if (rdev->pm.power_state) {
POWER_STATE_TYPE_DEFAULT; /* add the default mode */
rdev->pm.power_state[state_index].num_clock_modes = 1; rdev->pm.power_state[state_index].type =
rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk; POWER_STATE_TYPE_DEFAULT;
rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk; rdev->pm.power_state[state_index].num_clock_modes = 1;
rdev->pm.power_state[state_index].default_clock_mode = rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
&rdev->pm.power_state[state_index].clock_info[0]; rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; rdev->pm.power_state[state_index].default_clock_mode =
rdev->pm.power_state[state_index].pcie_lanes = 16; &rdev->pm.power_state[state_index].clock_info[0];
rdev->pm.default_power_state_index = state_index; rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
rdev->pm.power_state[state_index].flags = 0; rdev->pm.power_state[state_index].pcie_lanes = 16;
state_index++; rdev->pm.default_power_state_index = state_index;
rdev->pm.power_state[state_index].flags = 0;
state_index++;
}
} }
rdev->pm.num_power_states = state_index; rdev->pm.num_power_states = state_index;
......
...@@ -2442,6 +2442,17 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev) ...@@ -2442,6 +2442,17 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev)
rdev->pm.default_power_state_index = -1; rdev->pm.default_power_state_index = -1;
/* allocate 2 power states */
rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * 2, GFP_KERNEL);
if (!rdev->pm.power_state) {
rdev->pm.default_power_state_index = state_index;
rdev->pm.num_power_states = 0;
rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
rdev->pm.current_clock_mode_index = 0;
return;
}
if (rdev->flags & RADEON_IS_MOBILITY) { if (rdev->flags & RADEON_IS_MOBILITY) {
offset = combios_get_table_offset(dev, COMBIOS_POWERPLAY_INFO_TABLE); offset = combios_get_table_offset(dev, COMBIOS_POWERPLAY_INFO_TABLE);
if (offset) { if (offset) {
......
...@@ -646,6 +646,9 @@ void radeon_pm_fini(struct radeon_device *rdev) ...@@ -646,6 +646,9 @@ void radeon_pm_fini(struct radeon_device *rdev)
#endif #endif
} }
if (rdev->pm.power_state)
kfree(rdev->pm.power_state);
radeon_hwmon_fini(rdev); radeon_hwmon_fini(rdev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment