diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-05-01 14:34:54 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-05-02 11:53:07 -0400 |
commit | 441e76ca83ac604eaf0f046def96d8e3a27eea28 (patch) | |
tree | cc0584c06d08336a40340f9fcf0c1b653c16a09b | |
parent | 982cb32918f78730716213199787cc38202df33d (diff) |
drm/radeon: fix handling of v6 power tables
The code was mis-handling variable sized arrays.
Reported-by: Sylvain BERTRAND <sylware@legeek.net>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
-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 250db7021198..dea6f63c9724 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) | |||
2518 | int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); | 2518 | int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); |
2519 | u16 data_offset; | 2519 | u16 data_offset; |
2520 | u8 frev, crev; | 2520 | u8 frev, crev; |
2521 | u8 *power_state_offset; | ||
2521 | 2522 | ||
2522 | if (!atom_parse_data_header(mode_info->atom_context, index, NULL, | 2523 | if (!atom_parse_data_header(mode_info->atom_context, index, NULL, |
2523 | &frev, &crev, &data_offset)) | 2524 | &frev, &crev, &data_offset)) |
@@ -2540,11 +2541,11 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) | |||
2540 | state_array->ucNumEntries, GFP_KERNEL); | 2541 | state_array->ucNumEntries, GFP_KERNEL); |
2541 | if (!rdev->pm.power_state) | 2542 | if (!rdev->pm.power_state) |
2542 | return state_index; | 2543 | return state_index; |
2544 | power_state_offset = (u8 *)state_array->states; | ||
2543 | for (i = 0; i < state_array->ucNumEntries; i++) { | 2545 | for (i = 0; i < state_array->ucNumEntries; i++) { |
2544 | mode_index = 0; | 2546 | mode_index = 0; |
2545 | power_state = (union pplib_power_state *)&state_array->states[i]; | 2547 | power_state = (union pplib_power_state *)power_state_offset; |
2546 | /* XXX this might be an inagua bug... */ | 2548 | non_clock_array_index = power_state->v2.nonClockInfoIndex; |
2547 | non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */ | ||
2548 | non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) | 2549 | non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) |
2549 | &non_clock_info_array->nonClockInfo[non_clock_array_index]; | 2550 | &non_clock_info_array->nonClockInfo[non_clock_array_index]; |
2550 | rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) * | 2551 | 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) | |||
2556 | if (power_state->v2.ucNumDPMLevels) { | 2557 | if (power_state->v2.ucNumDPMLevels) { |
2557 | for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { | 2558 | for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { |
2558 | clock_array_index = power_state->v2.clockInfoIndex[j]; | 2559 | clock_array_index = power_state->v2.clockInfoIndex[j]; |
2559 | /* XXX this might be an inagua bug... */ | ||
2560 | if (clock_array_index >= clock_info_array->ucNumEntries) | ||
2561 | continue; | ||
2562 | clock_info = (union pplib_clock_info *) | 2560 | clock_info = (union pplib_clock_info *) |
2563 | &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; | 2561 | &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; |
2564 | valid = radeon_atombios_parse_pplib_clock_info(rdev, | 2562 | valid = radeon_atombios_parse_pplib_clock_info(rdev, |
@@ -2580,6 +2578,7 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) | |||
2580 | non_clock_info); | 2578 | non_clock_info); |
2581 | state_index++; | 2579 | state_index++; |
2582 | } | 2580 | } |
2581 | power_state_offset += 2 + power_state->v2.ucNumDPMLevels; | ||
2583 | } | 2582 | } |
2584 | /* if multiple clock modes, mark the lowest as no display */ | 2583 | /* if multiple clock modes, mark the lowest as no display */ |
2585 | for (i = 0; i < state_index; i++) { | 2584 | for (i = 0; i < state_index; i++) { |