freedreno: Mark all ringbuffer BOs as to be dumped on crash.
[mesa.git] / src / freedreno / drm / msm_ringbuffer_sp.c
index 2b8f531721e69801ede501123306e47ffa188a74..65bfb2bde80a22d71b01c2b804aee0714d4a908a 100644 (file)
@@ -41,8 +41,6 @@
 
 #define INIT_SIZE 0x1000
 
-static pthread_mutex_t idx_lock = PTHREAD_MUTEX_INITIALIZER;
-
 
 struct msm_submit_sp {
        struct fd_submit base;
@@ -50,12 +48,10 @@ struct msm_submit_sp {
        DECLARE_ARRAY(struct drm_msm_gem_submit_bo, submit_bos);
        DECLARE_ARRAY(struct fd_bo *, bos);
 
-       unsigned seqno;
-
        /* maps fd_bo to idx in bos table: */
        struct hash_table *bo_table;
 
-       struct slab_mempool ring_pool;
+       struct slab_child_pool ring_pool;
 
        struct fd_ringbuffer *primary;
 
@@ -120,14 +116,19 @@ static struct fd_ringbuffer * msm_ringbuffer_sp_init(
 
 /* add (if needed) bo to submit and return index: */
 static uint32_t
-append_bo(struct msm_submit_sp *submit, struct fd_bo *bo, uint32_t flags)
+msm_submit_append_bo(struct msm_submit_sp *submit, struct fd_bo *bo, uint32_t flags)
 {
        struct msm_bo *msm_bo = to_msm_bo(bo);
        uint32_t idx;
-       pthread_mutex_lock(&idx_lock);
-       if (likely(msm_bo->current_submit_seqno == submit->seqno)) {
-               idx = msm_bo->idx;
-       } else {
+
+       /* NOTE: it is legal to use the same bo on different threads for
+        * different submits.  But it is not legal to use the same submit
+        * from given threads.
+        */
+       idx = READ_ONCE(msm_bo->idx);
+
+       if (unlikely((idx >= submit->nr_submit_bos) ||
+                       (submit->submit_bos[idx].handle != bo->handle))) {
                uint32_t hash = _mesa_hash_pointer(bo);
                struct hash_entry *entry;
 
@@ -139,7 +140,7 @@ append_bo(struct msm_submit_sp *submit, struct fd_bo *bo, uint32_t flags)
                        idx = APPEND(submit, submit_bos);
                        idx = APPEND(submit, bos);
 
-                       submit->submit_bos[idx].flags = 0;
+                       submit->submit_bos[idx].flags = bo->flags;
                        submit->submit_bos[idx].handle = bo->handle;
                        submit->submit_bos[idx].presumed = 0;
 
@@ -148,16 +149,15 @@ append_bo(struct msm_submit_sp *submit, struct fd_bo *bo, uint32_t flags)
                        _mesa_hash_table_insert_pre_hashed(submit->bo_table, hash, bo,
                                        (void *)(uintptr_t)idx);
                }
-               msm_bo->current_submit_seqno = submit->seqno;
                msm_bo->idx = idx;
        }
-       pthread_mutex_unlock(&idx_lock);
-       if (flags & FD_RELOC_READ)
-               submit->submit_bos[idx].flags |= MSM_SUBMIT_BO_READ;
-       if (flags & FD_RELOC_WRITE)
-               submit->submit_bos[idx].flags |= MSM_SUBMIT_BO_WRITE;
-       if (flags & FD_RELOC_DUMP)
-               submit->submit_bos[idx].flags |= MSM_SUBMIT_BO_DUMP;
+
+       STATIC_ASSERT(FD_RELOC_READ == MSM_SUBMIT_BO_READ);
+       STATIC_ASSERT(FD_RELOC_WRITE == MSM_SUBMIT_BO_WRITE);
+       STATIC_ASSERT(FD_RELOC_DUMP == MSM_SUBMIT_BO_DUMP);
+       submit->submit_bos[idx].flags |=
+               flags & (MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE | MSM_SUBMIT_BO_DUMP);
+
        return idx;
 }
 
@@ -186,8 +186,7 @@ msm_submit_suballoc_ring_bo(struct fd_submit *submit,
 
        if (!suballoc_bo) {
                // TODO possibly larger size for streaming bo?
-               msm_ring->ring_bo = fd_bo_new_ring(submit->pipe->dev,
-                               0x8000, DRM_FREEDRENO_GEM_GPUREADONLY);
+               msm_ring->ring_bo = fd_bo_new_ring(submit->pipe->dev, 0x8000);
                msm_ring->offset = 0;
        } else {
                msm_ring->ring_bo = fd_bo_ref(suballoc_bo);
@@ -209,7 +208,7 @@ msm_submit_sp_new_ringbuffer(struct fd_submit *submit, uint32_t size,
        struct msm_submit_sp *msm_submit = to_msm_submit_sp(submit);
        struct msm_ringbuffer_sp *msm_ring;
 
-       msm_ring = slab_alloc_st(&msm_submit->ring_pool);
+       msm_ring = slab_alloc(&msm_submit->ring_pool);
 
        msm_ring->u.submit = submit;
 
@@ -225,8 +224,7 @@ msm_submit_sp_new_ringbuffer(struct fd_submit *submit, uint32_t size,
                        size = INIT_SIZE;
 
                msm_ring->offset = 0;
-               msm_ring->ring_bo = fd_bo_new_ring(submit->pipe->dev, size,
-                               DRM_FREEDRENO_GEM_GPUREADONLY);
+               msm_ring->ring_bo = fd_bo_new_ring(submit->pipe->dev, size);
        }
 
        if (!msm_ringbuffer_sp_init(msm_ring, size, flags))
@@ -260,8 +258,8 @@ msm_submit_sp_flush(struct fd_submit *submit, int in_fence_fd,
 
        for (unsigned i = 0; i < primary->u.nr_cmds; i++) {
                cmds[i].type = MSM_SUBMIT_CMD_BUF;
-               cmds[i].submit_idx = append_bo(msm_submit,
-                               primary->u.cmds[i].ring_bo, FD_RELOC_READ | FD_RELOC_DUMP);
+               cmds[i].submit_idx = msm_submit_append_bo(msm_submit,
+                               primary->u.cmds[i].ring_bo, 0);
                cmds[i].submit_offset = primary->offset;
                cmds[i].size = primary->u.cmds[i].size;
                cmds[i].pad = 0;
@@ -316,7 +314,7 @@ msm_submit_sp_destroy(struct fd_submit *submit)
        // TODO it would be nice to have a way to debug_assert() if all
        // rb's haven't been free'd back to the slab, because that is
        // an indication that we are leaking bo's
-       slab_destroy(&msm_submit->ring_pool);
+       slab_destroy_child(&msm_submit->ring_pool);
 
        for (unsigned i = 0; i < msm_submit->nr_bos; i++)
                fd_bo_del(msm_submit->bos[i]);
@@ -337,13 +335,11 @@ msm_submit_sp_new(struct fd_pipe *pipe)
 {
        struct msm_submit_sp *msm_submit = calloc(1, sizeof(*msm_submit));
        struct fd_submit *submit;
-       static unsigned submit_cnt = 0;
 
-       msm_submit->seqno = ++submit_cnt;
        msm_submit->bo_table = _mesa_hash_table_create(NULL,
                        _mesa_hash_pointer, _mesa_key_pointer_equal);
-       // TODO tune size:
-       slab_create(&msm_submit->ring_pool, sizeof(struct msm_ringbuffer_sp), 16);
+
+       slab_create_child(&msm_submit->ring_pool, &to_msm_pipe(pipe)->ring_pool);
 
        submit = &msm_submit->base;
        submit->pipe = pipe;
@@ -352,6 +348,19 @@ msm_submit_sp_new(struct fd_pipe *pipe)
        return submit;
 }
 
+void
+msm_pipe_sp_ringpool_init(struct msm_pipe *msm_pipe)
+{
+       // TODO tune size:
+       slab_create_parent(&msm_pipe->ring_pool, sizeof(struct msm_ringbuffer_sp), 16);
+}
+
+void
+msm_pipe_sp_ringpool_fini(struct msm_pipe *msm_pipe)
+{
+       if (msm_pipe->ring_pool.num_elements)
+               slab_destroy_parent(&msm_pipe->ring_pool);
+}
 
 static void
 finalize_current_cmd(struct fd_ringbuffer *ring)
@@ -376,8 +385,7 @@ msm_ringbuffer_sp_grow(struct fd_ringbuffer *ring, uint32_t size)
        finalize_current_cmd(ring);
 
        fd_bo_del(msm_ring->ring_bo);
-       msm_ring->ring_bo = fd_bo_new_ring(pipe->dev, size,
-                       DRM_FREEDRENO_GEM_GPUREADONLY);
+       msm_ring->ring_bo = fd_bo_new_ring(pipe->dev, size);
 
        ring->start = fd_bo_map(msm_ring->ring_bo);
        ring->end = &(ring->start[size/4]);
@@ -403,31 +411,25 @@ msm_ringbuffer_sp_emit_reloc(struct fd_ringbuffer *ring,
                struct msm_submit_sp *msm_submit =
                                to_msm_submit_sp(msm_ring->u.submit);
 
-               append_bo(msm_submit, reloc->bo, reloc->flags);
+               msm_submit_append_bo(msm_submit, reloc->bo, reloc->flags);
 
                pipe = msm_ring->u.submit->pipe;
        }
 
-       uint64_t iova = fd_bo_get_iova(reloc->bo) + reloc->offset;
-       uint32_t dword = iova;
+       uint64_t iova = reloc->bo->iova + reloc->offset;
        int shift = reloc->shift;
 
        if (shift < 0)
-               dword >>= -shift;
+               iova >>= -shift;
        else
-               dword <<= shift;
+               iova <<= shift;
+
+       uint32_t dword = iova;
 
        (*ring->cur++) = dword | reloc->or;
 
        if (pipe->gpu_id >= 500) {
                dword = iova >> 32;
-               shift -= 32;
-
-               if (shift < 0)
-                       dword >>= -shift;
-               else
-                       dword <<= shift;
-
                (*ring->cur++) = dword | reloc->orhi;
        }
 }
@@ -451,7 +453,6 @@ msm_ringbuffer_sp_emit_reloc_ring(struct fd_ringbuffer *ring,
 
        msm_ringbuffer_sp_emit_reloc(ring, &(struct fd_reloc){
                .bo     = bo,
-               .flags  = FD_RELOC_READ | FD_RELOC_DUMP,
                .offset = msm_target->offset,
        });
 
@@ -476,7 +477,7 @@ msm_ringbuffer_sp_emit_reloc_ring(struct fd_ringbuffer *ring,
                struct msm_submit_sp *msm_submit = to_msm_submit_sp(msm_ring->u.submit);
 
                for (unsigned i = 0; i < msm_target->u.nr_reloc_bos; i++) {
-                       append_bo(msm_submit, msm_target->u.reloc_bos[i].bo,
+                       msm_submit_append_bo(msm_submit, msm_target->u.reloc_bos[i].bo,
                                        msm_target->u.reloc_bos[i].flags);
                }
        }
@@ -503,6 +504,7 @@ msm_ringbuffer_sp_destroy(struct fd_ringbuffer *ring)
                for (unsigned i = 0; i < msm_ring->u.nr_reloc_bos; i++) {
                        fd_bo_del(msm_ring->u.reloc_bos[i].bo);
                }
+               free(msm_ring->u.reloc_bos);
 
                free(msm_ring);
        } else {
@@ -511,8 +513,9 @@ msm_ringbuffer_sp_destroy(struct fd_ringbuffer *ring)
                for (unsigned i = 0; i < msm_ring->u.nr_cmds; i++) {
                        fd_bo_del(msm_ring->u.cmds[i].ring_bo);
                }
+               free(msm_ring->u.cmds);
 
-               slab_free_st(&to_msm_submit_sp(submit)->ring_pool, msm_ring);
+               slab_free(&to_msm_submit_sp(submit)->ring_pool, msm_ring);
        }
 }
 
@@ -560,8 +563,7 @@ msm_ringbuffer_sp_new_object(struct fd_pipe *pipe, uint32_t size)
 
        msm_ring->u.pipe = pipe;
        msm_ring->offset = 0;
-       msm_ring->ring_bo = fd_bo_new_ring(pipe->dev, size,
-                       DRM_FREEDRENO_GEM_GPUREADONLY);
+       msm_ring->ring_bo = fd_bo_new_ring(pipe->dev, size);
        msm_ring->base.refcnt = 1;
 
        return msm_ringbuffer_sp_init(msm_ring, size, _FD_RINGBUFFER_OBJECT);