freedreno: don't leak stateobj rb refs
One stateobj can be emitted multiple times in a single cmdstream, but only the first time is a cmd entry added to the parent. Since it will be only unref'd once after flush, we should only ref it the first time it is emitted (ie. the time it is added to cmd table). Signed-off-by: Rob Clark <robclark@freedesktop.org>main
parent
f4f61e5ec8
commit
a43940eb91
|
@ -237,8 +237,11 @@ static int check_cmd_bo(struct fd_ringbuffer *ring,
|
||||||
|
|
||||||
/* Ensure that submit has corresponding entry in cmds table for the
|
/* Ensure that submit has corresponding entry in cmds table for the
|
||||||
* target cmdstream buffer:
|
* target cmdstream buffer:
|
||||||
|
*
|
||||||
|
* Returns TRUE if new cmd added (else FALSE if it was already in
|
||||||
|
* the cmds table)
|
||||||
*/
|
*/
|
||||||
static void get_cmd(struct fd_ringbuffer *ring, struct msm_cmd *target_cmd,
|
static int get_cmd(struct fd_ringbuffer *ring, struct msm_cmd *target_cmd,
|
||||||
uint32_t submit_offset, uint32_t size, uint32_t type)
|
uint32_t submit_offset, uint32_t size, uint32_t type)
|
||||||
{
|
{
|
||||||
struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
|
struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring);
|
||||||
|
@ -252,7 +255,7 @@ static void get_cmd(struct fd_ringbuffer *ring, struct msm_cmd *target_cmd,
|
||||||
(cmd->size == size) &&
|
(cmd->size == size) &&
|
||||||
(cmd->type == type) &&
|
(cmd->type == type) &&
|
||||||
check_cmd_bo(ring, cmd, target_cmd->ring_bo))
|
check_cmd_bo(ring, cmd, target_cmd->ring_bo))
|
||||||
return;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create cmd buf if not: */
|
/* create cmd buf if not: */
|
||||||
|
@ -267,6 +270,8 @@ static void get_cmd(struct fd_ringbuffer *ring, struct msm_cmd *target_cmd,
|
||||||
cmd->pad = 0;
|
cmd->pad = 0;
|
||||||
|
|
||||||
target_cmd->size = size;
|
target_cmd->size = size;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void * msm_ringbuffer_hostptr(struct fd_ringbuffer *ring)
|
static void * msm_ringbuffer_hostptr(struct fd_ringbuffer *ring)
|
||||||
|
@ -559,6 +564,7 @@ static uint32_t msm_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring,
|
||||||
{
|
{
|
||||||
struct msm_cmd *cmd = NULL;
|
struct msm_cmd *cmd = NULL;
|
||||||
uint32_t idx = 0;
|
uint32_t idx = 0;
|
||||||
|
int added_cmd = FALSE;
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY(cmd, &to_msm_ringbuffer(target)->cmd_list, list) {
|
LIST_FOR_EACH_ENTRY(cmd, &to_msm_ringbuffer(target)->cmd_list, list) {
|
||||||
if (idx == cmd_idx)
|
if (idx == cmd_idx)
|
||||||
|
@ -577,7 +583,8 @@ static uint32_t msm_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring,
|
||||||
size = cmd->size;
|
size = cmd->size;
|
||||||
} else {
|
} else {
|
||||||
struct fd_ringbuffer *parent = ring->parent ? ring->parent : ring;
|
struct fd_ringbuffer *parent = ring->parent ? ring->parent : ring;
|
||||||
get_cmd(parent, cmd, submit_offset, size, MSM_SUBMIT_CMD_IB_TARGET_BUF);
|
added_cmd = get_cmd(parent, cmd, submit_offset, size,
|
||||||
|
MSM_SUBMIT_CMD_IB_TARGET_BUF);
|
||||||
}
|
}
|
||||||
|
|
||||||
msm_ringbuffer_emit_reloc(ring, &(struct fd_reloc){
|
msm_ringbuffer_emit_reloc(ring, &(struct fd_reloc){
|
||||||
|
@ -590,7 +597,7 @@ static uint32_t msm_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring,
|
||||||
* being flushed), mesa can't really guarantee that a stateobj isn't
|
* being flushed), mesa can't really guarantee that a stateobj isn't
|
||||||
* destroyed after emitted but before flush, so we must hold a ref:
|
* destroyed after emitted but before flush, so we must hold a ref:
|
||||||
*/
|
*/
|
||||||
if (target->flags & FD_RINGBUFFER_OBJECT) {
|
if (added_cmd && (target->flags & FD_RINGBUFFER_OBJECT)) {
|
||||||
msm_ringbuffer_ref(target);
|
msm_ringbuffer_ref(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue