diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-05-01 18:34:54 (GMT) |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-05-11 20:54:09 (GMT) |
commit | d7a0a30e6fcba4c014fedfdb56e19837f8030ea9 (patch) | |
tree | 16c1009f0819242bf8682354362829b1c2b3b30b /drivers | |
parent | 9c9a03e19d6414c7c6f482d8130c7592cbd0ef6a (diff) | |
download | linux-fsl-qoriq-d7a0a30e6fcba4c014fedfdb56e19837f8030ea9.tar.xz |
drm/radeon: fix handling of v6 power tables
commit 441e76ca83ac604eaf0f046def96d8e3a27eea28 upstream.
The code was mis-handling variable sized arrays.
Reported-by: Sylvain BERTRAND <sylware@legeek.net>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atombios.c | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 8a9b27cb3..96168ef 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -2518,6 +2518,7 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); u16 data_offset; u8 frev, crev; + u8 *power_state_offset; if (!atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset)) @@ -2540,11 +2541,11 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) state_array->ucNumEntries, GFP_KERNEL); if (!rdev->pm.power_state) return state_index; + power_state_offset = (u8 *)state_array->states; for (i = 0; i < state_array->ucNumEntries; i++) { mode_index = 0; - power_state = (union pplib_power_state *)&state_array->states[i]; - /* XXX this might be an inagua bug... */ - non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */ + power_state = (union pplib_power_state *)power_state_offset; + non_clock_array_index = power_state->v2.nonClockInfoIndex; non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) &non_clock_info_array->nonClockInfo[non_clock_array_index]; rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) * @@ -2556,9 +2557,6 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) if (power_state->v2.ucNumDPMLevels) { for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { clock_array_index = power_state->v2.clockInfoIndex[j]; - /* XXX this might be an inagua bug... */ - if (clock_array_index >= clock_info_array->ucNumEntries) - continue; clock_info = (union pplib_clock_info *) &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; valid = radeon_atombios_parse_pplib_clock_info(rdev, @@ -2580,6 +2578,7 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) non_clock_info); state_index++; } + power_state_offset += 2 + power_state->v2.ucNumDPMLevels; } /* if multiple clock modes, mark the lowest as no display */ for (i = 0; i < state_index; i++) { |