v3dv: don't leak BOs from CLs when using BRANCH

Keep the list of BOs referenced in the CL and free all of them
when the CL is destroyed.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
diff --git a/src/broadcom/vulkan/v3dv_bo.c b/src/broadcom/vulkan/v3dv_bo.c
index a63e61b..5926ab9 100644
--- a/src/broadcom/vulkan/v3dv_bo.c
+++ b/src/broadcom/vulkan/v3dv_bo.c
@@ -60,6 +60,7 @@
    bo->map = NULL;
    bo->map_size = 0;
    bo->name = name;
+   list_inithead(&bo->list_link);
 
    return bo;
 }
diff --git a/src/broadcom/vulkan/v3dv_bo.h b/src/broadcom/vulkan/v3dv_bo.h
index 41337ee..270022d 100644
--- a/src/broadcom/vulkan/v3dv_bo.h
+++ b/src/broadcom/vulkan/v3dv_bo.h
@@ -27,6 +27,8 @@
 struct v3dv_device;
 
 struct v3dv_bo {
+   struct list_head list_link;
+
    uint32_t handle;
    uint32_t size;
    uint32_t offset;
diff --git a/src/broadcom/vulkan/v3dv_cl.c b/src/broadcom/vulkan/v3dv_cl.c
index 9aab7b8..c3a9120 100644
--- a/src/broadcom/vulkan/v3dv_cl.c
+++ b/src/broadcom/vulkan/v3dv_cl.c
@@ -32,6 +32,7 @@
    cl->bo = NULL;
    cl->size = 0;
    cl->job = job;
+   list_inithead(&cl->bo_list);
 }
 
 void
@@ -52,15 +53,52 @@
 void
 v3dv_cl_destroy(struct v3dv_cl *cl)
 {
-   if (cl->bo) {
+   list_for_each_entry_safe(struct v3dv_bo, bo, &cl->bo_list, list_link) {
       assert(cl->job);
-      v3dv_bo_free(cl->job->device, cl->bo);
+      list_del(&bo->list_link);
+      v3dv_bo_free(cl->job->device, bo);
    }
 
    /* Leave the CL in a reset state to catch use after destroy instances */
    v3dv_cl_init(NULL, cl);
 }
 
+static bool
+cl_alloc_bo(struct v3dv_cl *cl, uint32_t space, bool use_branch)
+{
+   struct v3dv_bo *bo = v3dv_bo_alloc(cl->job->device, space, "CL");
+   if (!bo) {
+      fprintf(stderr, "failed to allocate memory for command list\n");
+      v3dv_flag_oom(NULL, cl->job);
+      return false;
+   }
+
+   list_addtail(&bo->list_link, &cl->bo_list);
+
+   bool ok = v3dv_bo_map(cl->job->device, bo, bo->size);
+   if (!ok) {
+      fprintf(stderr, "failed to map command list buffer\n");
+      v3dv_flag_oom(NULL, cl->job);
+      return false;
+   }
+
+   /* Chain to the new BO from the old one if requested */
+   if (use_branch && cl->bo) {
+      cl_emit(cl, BRANCH, branch) {
+         branch.address = v3dv_cl_address(bo, 0);
+      }
+   }
+
+   v3dv_job_add_bo(cl->job, bo);
+
+   cl->bo = bo;
+   cl->base = cl->bo->map;
+   cl->size = cl->bo->size;
+   cl->next = cl->base;
+
+   return true;
+}
+
 uint32_t
 v3dv_cl_ensure_space(struct v3dv_cl *cl, uint32_t space, uint32_t alignment)
 {
@@ -71,27 +109,7 @@
       return offset;
    }
 
-   struct v3dv_bo *bo = v3dv_bo_alloc(cl->job->device, space, "CL");
-   if (!bo) {
-      fprintf(stderr, "failed to allocate memory for command list\n");
-      v3dv_flag_oom(NULL, cl->job);
-      return 0;
-   }
-
-   v3dv_job_add_bo(cl->job, bo);
-
-   bool ok = v3dv_bo_map(cl->job->device, bo, bo->size);
-   if (!ok) {
-      fprintf(stderr, "failed to map command list buffer\n");
-      v3dv_flag_oom(NULL, cl->job);
-      return 0;
-   }
-
-   cl->bo = bo;
-   cl->base = cl->bo->map;
-   cl->size = cl->bo->size;
-   cl->next = cl->base;
-
+   cl_alloc_bo(cl, space, false);
    return 0;
 }
 
@@ -101,31 +119,5 @@
    if (v3dv_cl_offset(cl) + space + cl_packet_length(BRANCH) <= cl->size)
       return;
 
-   struct v3dv_bo *bo = v3dv_bo_alloc(cl->job->device, space, "CL");
-   if (!bo) {
-      fprintf(stderr, "failed to allocate memory for command list\n");
-      v3dv_flag_oom(NULL, cl->job);
-      return;
-   }
-
-   /* Chain to the new BO from the old one if needed */
-   if (cl->bo) {
-      cl_emit(cl, BRANCH, branch) {
-         branch.address = v3dv_cl_address(bo, 0);
-      }
-   }
-
-   v3dv_job_add_bo(cl->job, bo);
-
-   bool ok = v3dv_bo_map(cl->job->device, bo, bo->size);
-   if (!ok) {
-      fprintf(stderr, "failed to map command list buffer\n");
-      v3dv_flag_oom(NULL, cl->job);
-      return;
-   }
-
-   cl->bo = bo;
-   cl->base = cl->bo->map;
-   cl->size = cl->bo->size;
-   cl->next = cl->base;
+   cl_alloc_bo(cl, space, true);
 }
diff --git a/src/broadcom/vulkan/v3dv_cl.h b/src/broadcom/vulkan/v3dv_cl.h
index 03d328c..cd5196c 100644
--- a/src/broadcom/vulkan/v3dv_cl.h
+++ b/src/broadcom/vulkan/v3dv_cl.h
@@ -26,6 +26,8 @@
 
 #include "broadcom/cle/v3d_packet_helpers.h"
 
+#include "list.h"
+
 struct v3dv_bo;
 struct v3dv_job;
 struct v3dv_cl;
@@ -50,6 +52,7 @@
    struct v3dv_cl_out *next;
    struct v3dv_bo *bo;
    uint32_t size;
+   struct list_head bo_list;
 };
 
 static inline struct v3dv_cl_reloc