* lasts for the duration of the submit-ioctl.
  */
 struct etnaviv_gem_submit {
+       struct kref refcount;
        struct etnaviv_gpu *gpu;
        struct dma_fence *out_fence, *in_fence;
        u32 flags;
        /* No new members here, the previous one is variable-length! */
 };
 
+void etnaviv_submit_put(struct etnaviv_gem_submit * submit);
+
 int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_object *obj,
        struct timespec *timeout);
 int etnaviv_gem_new_private(struct drm_device *dev, size_t size, u32 flags,
 
                return NULL;
 
        submit->gpu = gpu;
+       kref_init(&submit->refcount);
 
        return submit;
 }
        return 0;
 }
 
-static void submit_cleanup(struct etnaviv_gem_submit *submit)
+static void submit_cleanup(struct kref *kref)
 {
+       struct etnaviv_gem_submit *submit =
+                       container_of(kref, struct etnaviv_gem_submit, refcount);
        unsigned i;
 
        for (i = 0; i < submit->nr_bos; i++) {
        kfree(submit);
 }
 
+void etnaviv_submit_put(struct etnaviv_gem_submit *submit)
+{
+       kref_put(&submit->refcount, submit_cleanup);
+}
+
 int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
                struct drm_file *file)
 {
        args->fence = submit->out_fence->seqno;
 
 err_submit_objects:
-       submit_cleanup(submit);
+       etnaviv_submit_put(submit);
 
 err_submit_ww_acquire:
        ww_acquire_fini(&ticket);