Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions drivers/gpu/drm/vc4/vc4_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,11 @@ struct vc4_exec_info {
* (where each tile's binned CL will start)
*/
uint32_t tile_alloc_offset;
/* Stride between adjacent tiles' initial alloc blocks. Equals the
* initial block size programmed in the binning config, and is used
* as the per-tile stride when emitting the RCL branches.
*/
u32 tile_alloc_stride;
/* Bitmask of which binner slots are freed when this job completes. */
uint32_t bin_slots;

Expand Down
14 changes: 13 additions & 1 deletion drivers/gpu/drm/vc4/vc4_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ vc4_overflow_mem_work(struct work_struct *work)
vc4->bin_alloc_overflow = BIT(bin_bo_slot);

V3D_WRITE(V3D_BPOA, bo->base.dma_addr + bin_bo_slot * vc4->bin_alloc_size);
V3D_WRITE(V3D_BPOS, bo->base.base.size);
V3D_WRITE(V3D_BPOS, vc4->bin_alloc_size);
V3D_WRITE(V3D_INTCTL, V3D_INT_OUTOMEM);
V3D_WRITE(V3D_INTENA, V3D_INT_OUTOMEM);
spin_unlock_irqrestore(&vc4->job_lock, irqflags);
Expand Down Expand Up @@ -352,6 +352,18 @@ void vc4_irq_reset(struct drm_device *dev)
V3D_WRITE(V3D_INTENA, V3D_DRIVER_IRQS);

spin_lock_irqsave(&vc4->job_lock, irqflags);

/*
* The reset wiped the binner's hardware state, and the job that may
* have been reading overflow memory is torn down just below. Free the
* current overflow slot and clear the overflow registers so the
* re-queued BIN job restarts from a clean OOM state.
*/
vc4->bin_alloc_used &= ~vc4->bin_alloc_overflow;
vc4->bin_alloc_overflow = 0;
V3D_WRITE(V3D_BPOA, 0);
V3D_WRITE(V3D_BPOS, 0);

vc4_cancel_bin_job(dev);
vc4_irq_finish_render_job(dev);
spin_unlock_irqrestore(&vc4->job_lock, irqflags);
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/vc4/vc4_render_cl.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,8 @@ static void emit_tile(struct vc4_exec_info *exec,
if (has_bin) {
rcl_u8(setup, VC4_PACKET_BRANCH_TO_SUB_LIST);
rcl_u32(setup, (exec->tile_alloc_offset +
(y * exec->bin_tiles_x + x) * 32));
(y * exec->bin_tiles_x + x) *
exec->tile_alloc_stride));
}

if (setup->msaa_color_write) {
Expand Down
29 changes: 26 additions & 3 deletions drivers/gpu/drm/vc4/vc4_validate.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,9 @@ validate_tile_binning_config(VALIDATE_ARGS)
struct drm_device *dev = exec->exec_bo->base.dev;
struct vc4_dev *vc4 = to_vc4_dev(dev);
uint8_t flags;
uint32_t tile_state_size;
u32 tile_state_size, tile_state_aligned;
uint32_t tile_count, bin_addr;
u8 init_block;
int bin_slot;

if (exec->found_tile_binning_mode_config_packet) {
Expand Down Expand Up @@ -405,13 +406,35 @@ validate_tile_binning_config(VALIDATE_ARGS)
tile_state_size = 48 * tile_count;

/* Since the tile alloc array will follow us, align. */
exec->tile_alloc_offset = bin_addr + roundup(tile_state_size, 4096);
tile_state_aligned = roundup(tile_state_size, 4096);
exec->tile_alloc_offset = bin_addr + tile_state_aligned;

/*
* Pick the largest initial tile-alloc block that still fits the slot.
* Larger initial blocks keep more tiles' binned lists off the
* continuation-block chain, which the binner does not always link
* reliably. Denser tile counts fall back to smaller blocks, down to
* the 32-byte minimum which always fits.
*/
if (tile_state_aligned + 256 * tile_count <= vc4->bin_alloc_size) {
exec->tile_alloc_stride = 256;
init_block = VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_256;
} else if (tile_state_aligned + 128 * tile_count <= vc4->bin_alloc_size) {
exec->tile_alloc_stride = 128;
init_block = VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_128;
} else if (tile_state_aligned + 64 * tile_count <= vc4->bin_alloc_size) {
exec->tile_alloc_stride = 64;
init_block = VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_64;
} else {
exec->tile_alloc_stride = 32;
init_block = VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_32;
}

*(uint8_t *)(validated + 14) =
((flags & ~(VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_MASK |
VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_MASK)) |
VC4_BIN_CONFIG_AUTO_INIT_TSDA |
VC4_SET_FIELD(VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_32,
VC4_SET_FIELD(init_block,
VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE) |
VC4_SET_FIELD(VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE_128,
VC4_BIN_CONFIG_ALLOC_BLOCK_SIZE));
Expand Down
Loading