Skip to content

Commit

Permalink
drm/radeon/kms: re-emit full context state for evergreen blits
Browse files Browse the repository at this point in the history
clear state doesn't seem to work properly in some cases

Fixes hangs in heavy 3D on some evergreen cards reported on
IRC.

May fix:
https://bugs.freedesktop.org/show_bug.cgi?id=33381
possibly others.

Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Cc: stable@kernel.org
Signed-off-by: Dave Airlie <airlied@gmail.com>
  • Loading branch information
Alex Deucher authored and Dave Airlie committed Jan 28, 2011
1 parent dca0d61 commit 1e644d6
Showing 1 changed file with 33 additions and 6 deletions.
39 changes: 33 additions & 6 deletions drivers/gpu/drm/radeon/evergreen_blit_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ draw_auto(struct radeon_device *rdev)

}

/* emits 30 */
/* emits 34 */
static void
set_default_state(struct radeon_device *rdev)
{
Expand All @@ -245,6 +245,8 @@ set_default_state(struct radeon_device *rdev)
int num_hs_threads, num_ls_threads;
int num_ps_stack_entries, num_vs_stack_entries, num_gs_stack_entries, num_es_stack_entries;
int num_hs_stack_entries, num_ls_stack_entries;
u64 gpu_addr;
int dwords;

switch (rdev->family) {
case CHIP_CEDAR:
Expand Down Expand Up @@ -497,6 +499,14 @@ set_default_state(struct radeon_device *rdev)
radeon_ring_write(rdev, 0x00000000);
radeon_ring_write(rdev, 0x00000000);

/* emit an IB pointing at default state */
dwords = ALIGN(rdev->r600_blit.state_len, 0x10);
gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.state_offset;
radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
radeon_ring_write(rdev, gpu_addr & 0xFFFFFFFC);
radeon_ring_write(rdev, upper_32_bits(gpu_addr) & 0xFF);
radeon_ring_write(rdev, dwords);

}

static inline uint32_t i2f(uint32_t input)
Expand Down Expand Up @@ -527,17 +537,28 @@ static inline uint32_t i2f(uint32_t input)
int evergreen_blit_init(struct radeon_device *rdev)
{
u32 obj_size;
int r;
int r, dwords;
void *ptr;
u32 packet2s[16];
int num_packet2s = 0;

/* pin copy shader into vram if already initialized */
if (rdev->r600_blit.shader_obj)
goto done;

mutex_init(&rdev->r600_blit.mutex);
rdev->r600_blit.state_offset = 0;
rdev->r600_blit.state_len = 0;
obj_size = 0;

rdev->r600_blit.state_len = evergreen_default_size;

dwords = rdev->r600_blit.state_len;
while (dwords & 0xf) {
packet2s[num_packet2s++] = PACKET2(0);
dwords++;
}

obj_size = dwords * 4;
obj_size = ALIGN(obj_size, 256);

rdev->r600_blit.vs_offset = obj_size;
obj_size += evergreen_vs_size * 4;
Expand Down Expand Up @@ -567,6 +588,12 @@ int evergreen_blit_init(struct radeon_device *rdev)
return r;
}

memcpy_toio(ptr + rdev->r600_blit.state_offset,
evergreen_default_state, rdev->r600_blit.state_len * 4);

if (num_packet2s)
memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4),
packet2s, num_packet2s * 4);
memcpy(ptr + rdev->r600_blit.vs_offset, evergreen_vs, evergreen_vs_size * 4);
memcpy(ptr + rdev->r600_blit.ps_offset, evergreen_ps, evergreen_ps_size * 4);
radeon_bo_kunmap(rdev->r600_blit.shader_obj);
Expand Down Expand Up @@ -652,15 +679,15 @@ int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes)
/* calculate number of loops correctly */
ring_size = num_loops * dwords_per_loop;
/* set default + shaders */
ring_size += 46; /* shaders + def state */
ring_size += 50; /* shaders + def state */
ring_size += 10; /* fence emit for VB IB */
ring_size += 5; /* done copy */
ring_size += 10; /* fence emit for done copy */
r = radeon_ring_lock(rdev, ring_size);
if (r)
return r;

set_default_state(rdev); /* 30 */
set_default_state(rdev); /* 34 */
set_shaders(rdev); /* 16 */
return 0;
}
Expand Down

0 comments on commit 1e644d6

Please sign in to comment.