1d722e3fbSopenharmony_ci/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ 2d722e3fbSopenharmony_ci 3d722e3fbSopenharmony_ci/* 4d722e3fbSopenharmony_ci * Copyright (C) 2013 Rob Clark <robclark@freedesktop.org> 5d722e3fbSopenharmony_ci * 6d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"), 8d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation 9d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 11d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions: 12d722e3fbSopenharmony_ci * 13d722e3fbSopenharmony_ci * The above copyright notice and this permission notice (including the next 14d722e3fbSopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 15d722e3fbSopenharmony_ci * Software. 16d722e3fbSopenharmony_ci * 17d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20d722e3fbSopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21d722e3fbSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22d722e3fbSopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23d722e3fbSopenharmony_ci * SOFTWARE. 24d722e3fbSopenharmony_ci * 25d722e3fbSopenharmony_ci * Authors: 26d722e3fbSopenharmony_ci * Rob Clark <robclark@freedesktop.org> 27d722e3fbSopenharmony_ci */ 28d722e3fbSopenharmony_ci 29d722e3fbSopenharmony_ci#include <assert.h> 30d722e3fbSopenharmony_ci#include <inttypes.h> 31d722e3fbSopenharmony_ci 32d722e3fbSopenharmony_ci#include "xf86atomic.h" 33d722e3fbSopenharmony_ci#include "freedreno_ringbuffer.h" 34d722e3fbSopenharmony_ci#include "msm_priv.h" 35d722e3fbSopenharmony_ci 36d722e3fbSopenharmony_ci/* represents a single cmd buffer in the submit ioctl. Each cmd buffer has 37d722e3fbSopenharmony_ci * a backing bo, and a reloc table. 38d722e3fbSopenharmony_ci */ 39d722e3fbSopenharmony_cistruct msm_cmd { 40d722e3fbSopenharmony_ci struct list_head list; 41d722e3fbSopenharmony_ci 42d722e3fbSopenharmony_ci struct fd_ringbuffer *ring; 43d722e3fbSopenharmony_ci struct fd_bo *ring_bo; 44d722e3fbSopenharmony_ci 45d722e3fbSopenharmony_ci /* reloc's table: */ 46d722e3fbSopenharmony_ci DECLARE_ARRAY(struct drm_msm_gem_submit_reloc, relocs); 47d722e3fbSopenharmony_ci 48d722e3fbSopenharmony_ci uint32_t size; 49d722e3fbSopenharmony_ci 50d722e3fbSopenharmony_ci /* has cmd already been added to parent rb's submit.cmds table? */ 51d722e3fbSopenharmony_ci int is_appended_to_submit; 52d722e3fbSopenharmony_ci}; 53d722e3fbSopenharmony_ci 54d722e3fbSopenharmony_cistruct msm_ringbuffer { 55d722e3fbSopenharmony_ci struct fd_ringbuffer base; 56d722e3fbSopenharmony_ci 57d722e3fbSopenharmony_ci /* submit ioctl related tables: 58d722e3fbSopenharmony_ci * Note that bos and cmds are tracked by the parent ringbuffer, since 59d722e3fbSopenharmony_ci * that is global to the submit ioctl call. The reloc's table is tracked 60d722e3fbSopenharmony_ci * per cmd-buffer. 61d722e3fbSopenharmony_ci */ 62d722e3fbSopenharmony_ci struct { 63d722e3fbSopenharmony_ci /* bo's table: */ 64d722e3fbSopenharmony_ci DECLARE_ARRAY(struct drm_msm_gem_submit_bo, bos); 65d722e3fbSopenharmony_ci 66d722e3fbSopenharmony_ci /* cmd's table: */ 67d722e3fbSopenharmony_ci DECLARE_ARRAY(struct drm_msm_gem_submit_cmd, cmds); 68d722e3fbSopenharmony_ci } submit; 69d722e3fbSopenharmony_ci 70d722e3fbSopenharmony_ci /* should have matching entries in submit.bos: */ 71d722e3fbSopenharmony_ci /* Note, only in parent ringbuffer */ 72d722e3fbSopenharmony_ci DECLARE_ARRAY(struct fd_bo *, bos); 73d722e3fbSopenharmony_ci 74d722e3fbSopenharmony_ci /* should have matching entries in submit.cmds: */ 75d722e3fbSopenharmony_ci DECLARE_ARRAY(struct msm_cmd *, cmds); 76d722e3fbSopenharmony_ci 77d722e3fbSopenharmony_ci /* List of physical cmdstream buffers (msm_cmd) associated with this 78d722e3fbSopenharmony_ci * logical fd_ringbuffer. 79d722e3fbSopenharmony_ci * 80d722e3fbSopenharmony_ci * Note that this is different from msm_ringbuffer::cmds (which 81d722e3fbSopenharmony_ci * shadows msm_ringbuffer::submit::cmds for tracking submit ioctl 82d722e3fbSopenharmony_ci * related stuff, and *only* is tracked in the parent ringbuffer. 83d722e3fbSopenharmony_ci * And only has "completed" cmd buffers (ie. we already know the 84d722e3fbSopenharmony_ci * size) added via get_cmd(). 85d722e3fbSopenharmony_ci */ 86d722e3fbSopenharmony_ci struct list_head cmd_list; 87d722e3fbSopenharmony_ci 88d722e3fbSopenharmony_ci int is_growable; 89d722e3fbSopenharmony_ci unsigned cmd_count; 90d722e3fbSopenharmony_ci 91d722e3fbSopenharmony_ci unsigned offset; /* for sub-allocated stateobj rb's */ 92d722e3fbSopenharmony_ci 93d722e3fbSopenharmony_ci unsigned seqno; 94d722e3fbSopenharmony_ci 95d722e3fbSopenharmony_ci /* maps fd_bo to idx: */ 96d722e3fbSopenharmony_ci void *bo_table; 97d722e3fbSopenharmony_ci 98d722e3fbSopenharmony_ci /* maps msm_cmd to drm_msm_gem_submit_cmd in parent rb. Each rb has a 99d722e3fbSopenharmony_ci * list of msm_cmd's which correspond to each chunk of cmdstream in 100d722e3fbSopenharmony_ci * a 'growable' rb. For each of those we need to create one 101d722e3fbSopenharmony_ci * drm_msm_gem_submit_cmd in the parent rb which collects the state 102d722e3fbSopenharmony_ci * for the submit ioctl. Because we can have multiple IB's to the same 103d722e3fbSopenharmony_ci * target rb (for example, or same stateobj emit multiple times), and 104d722e3fbSopenharmony_ci * because in theory we can have multiple different rb's that have a 105d722e3fbSopenharmony_ci * reference to a given target, we need a hashtable to track this per 106d722e3fbSopenharmony_ci * rb. 107d722e3fbSopenharmony_ci */ 108d722e3fbSopenharmony_ci void *cmd_table; 109d722e3fbSopenharmony_ci}; 110d722e3fbSopenharmony_ci 111d722e3fbSopenharmony_cistatic inline struct msm_ringbuffer * to_msm_ringbuffer(struct fd_ringbuffer *x) 112d722e3fbSopenharmony_ci{ 113d722e3fbSopenharmony_ci return (struct msm_ringbuffer *)x; 114d722e3fbSopenharmony_ci} 115d722e3fbSopenharmony_ci 116d722e3fbSopenharmony_ci#define INIT_SIZE 0x1000 117d722e3fbSopenharmony_ci 118d722e3fbSopenharmony_cistatic pthread_mutex_t idx_lock = PTHREAD_MUTEX_INITIALIZER; 119d722e3fbSopenharmony_ci 120d722e3fbSopenharmony_cistatic struct msm_cmd *current_cmd(struct fd_ringbuffer *ring) 121d722e3fbSopenharmony_ci{ 122d722e3fbSopenharmony_ci struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); 123d722e3fbSopenharmony_ci assert(!LIST_IS_EMPTY(&msm_ring->cmd_list)); 124d722e3fbSopenharmony_ci return LIST_LAST_ENTRY(&msm_ring->cmd_list, struct msm_cmd, list); 125d722e3fbSopenharmony_ci} 126d722e3fbSopenharmony_ci 127d722e3fbSopenharmony_cistatic void ring_cmd_del(struct msm_cmd *cmd) 128d722e3fbSopenharmony_ci{ 129d722e3fbSopenharmony_ci fd_bo_del(cmd->ring_bo); 130d722e3fbSopenharmony_ci list_del(&cmd->list); 131d722e3fbSopenharmony_ci to_msm_ringbuffer(cmd->ring)->cmd_count--; 132d722e3fbSopenharmony_ci free(cmd->relocs); 133d722e3fbSopenharmony_ci free(cmd); 134d722e3fbSopenharmony_ci} 135d722e3fbSopenharmony_ci 136d722e3fbSopenharmony_cistatic struct msm_cmd * ring_cmd_new(struct fd_ringbuffer *ring, uint32_t size, 137d722e3fbSopenharmony_ci enum fd_ringbuffer_flags flags) 138d722e3fbSopenharmony_ci{ 139d722e3fbSopenharmony_ci struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); 140d722e3fbSopenharmony_ci struct msm_cmd *cmd = calloc(1, sizeof(*cmd)); 141d722e3fbSopenharmony_ci 142d722e3fbSopenharmony_ci if (!cmd) 143d722e3fbSopenharmony_ci return NULL; 144d722e3fbSopenharmony_ci 145d722e3fbSopenharmony_ci cmd->ring = ring; 146d722e3fbSopenharmony_ci 147d722e3fbSopenharmony_ci /* TODO separate suballoc buffer for small non-streaming state, using 148d722e3fbSopenharmony_ci * smaller page-sized backing bo's. 149d722e3fbSopenharmony_ci */ 150d722e3fbSopenharmony_ci if (flags & FD_RINGBUFFER_STREAMING) { 151d722e3fbSopenharmony_ci struct msm_pipe *msm_pipe = to_msm_pipe(ring->pipe); 152d722e3fbSopenharmony_ci unsigned suballoc_offset = 0; 153d722e3fbSopenharmony_ci struct fd_bo *suballoc_bo = NULL; 154d722e3fbSopenharmony_ci 155d722e3fbSopenharmony_ci if (msm_pipe->suballoc_ring) { 156d722e3fbSopenharmony_ci struct msm_ringbuffer *suballoc_ring = to_msm_ringbuffer(msm_pipe->suballoc_ring); 157d722e3fbSopenharmony_ci 158d722e3fbSopenharmony_ci assert(msm_pipe->suballoc_ring->flags & FD_RINGBUFFER_OBJECT); 159d722e3fbSopenharmony_ci assert(suballoc_ring->cmd_count == 1); 160d722e3fbSopenharmony_ci 161d722e3fbSopenharmony_ci suballoc_bo = current_cmd(msm_pipe->suballoc_ring)->ring_bo; 162d722e3fbSopenharmony_ci 163d722e3fbSopenharmony_ci suballoc_offset = fd_ringbuffer_size(msm_pipe->suballoc_ring) + 164d722e3fbSopenharmony_ci suballoc_ring->offset; 165d722e3fbSopenharmony_ci 166d722e3fbSopenharmony_ci suballoc_offset = ALIGN(suballoc_offset, 0x10); 167d722e3fbSopenharmony_ci 168d722e3fbSopenharmony_ci if ((size + suballoc_offset) > suballoc_bo->size) { 169d722e3fbSopenharmony_ci suballoc_bo = NULL; 170d722e3fbSopenharmony_ci } 171d722e3fbSopenharmony_ci } 172d722e3fbSopenharmony_ci 173d722e3fbSopenharmony_ci if (!suballoc_bo) { 174d722e3fbSopenharmony_ci cmd->ring_bo = fd_bo_new_ring(ring->pipe->dev, 0x8000, 0); 175d722e3fbSopenharmony_ci msm_ring->offset = 0; 176d722e3fbSopenharmony_ci } else { 177d722e3fbSopenharmony_ci cmd->ring_bo = fd_bo_ref(suballoc_bo); 178d722e3fbSopenharmony_ci msm_ring->offset = suballoc_offset; 179d722e3fbSopenharmony_ci } 180d722e3fbSopenharmony_ci 181d722e3fbSopenharmony_ci if (msm_pipe->suballoc_ring) 182d722e3fbSopenharmony_ci fd_ringbuffer_del(msm_pipe->suballoc_ring); 183d722e3fbSopenharmony_ci 184d722e3fbSopenharmony_ci msm_pipe->suballoc_ring = fd_ringbuffer_ref(ring); 185d722e3fbSopenharmony_ci } else { 186d722e3fbSopenharmony_ci cmd->ring_bo = fd_bo_new_ring(ring->pipe->dev, size, 0); 187d722e3fbSopenharmony_ci } 188d722e3fbSopenharmony_ci if (!cmd->ring_bo) 189d722e3fbSopenharmony_ci goto fail; 190d722e3fbSopenharmony_ci 191d722e3fbSopenharmony_ci list_addtail(&cmd->list, &msm_ring->cmd_list); 192d722e3fbSopenharmony_ci msm_ring->cmd_count++; 193d722e3fbSopenharmony_ci 194d722e3fbSopenharmony_ci return cmd; 195d722e3fbSopenharmony_ci 196d722e3fbSopenharmony_cifail: 197d722e3fbSopenharmony_ci ring_cmd_del(cmd); 198d722e3fbSopenharmony_ci return NULL; 199d722e3fbSopenharmony_ci} 200d722e3fbSopenharmony_ci 201d722e3fbSopenharmony_cistatic uint32_t append_bo(struct fd_ringbuffer *ring, struct fd_bo *bo) 202d722e3fbSopenharmony_ci{ 203d722e3fbSopenharmony_ci struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); 204d722e3fbSopenharmony_ci uint32_t idx; 205d722e3fbSopenharmony_ci 206d722e3fbSopenharmony_ci idx = APPEND(&msm_ring->submit, bos); 207d722e3fbSopenharmony_ci idx = APPEND(msm_ring, bos); 208d722e3fbSopenharmony_ci 209d722e3fbSopenharmony_ci msm_ring->submit.bos[idx].flags = 0; 210d722e3fbSopenharmony_ci msm_ring->submit.bos[idx].handle = bo->handle; 211d722e3fbSopenharmony_ci msm_ring->submit.bos[idx].presumed = to_msm_bo(bo)->presumed; 212d722e3fbSopenharmony_ci 213d722e3fbSopenharmony_ci msm_ring->bos[idx] = fd_bo_ref(bo); 214d722e3fbSopenharmony_ci 215d722e3fbSopenharmony_ci return idx; 216d722e3fbSopenharmony_ci} 217d722e3fbSopenharmony_ci 218d722e3fbSopenharmony_ci/* add (if needed) bo, return idx: */ 219d722e3fbSopenharmony_cistatic uint32_t bo2idx(struct fd_ringbuffer *ring, struct fd_bo *bo, uint32_t flags) 220d722e3fbSopenharmony_ci{ 221d722e3fbSopenharmony_ci struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); 222d722e3fbSopenharmony_ci struct msm_bo *msm_bo = to_msm_bo(bo); 223d722e3fbSopenharmony_ci uint32_t idx; 224d722e3fbSopenharmony_ci pthread_mutex_lock(&idx_lock); 225d722e3fbSopenharmony_ci if (msm_bo->current_ring_seqno == msm_ring->seqno) { 226d722e3fbSopenharmony_ci idx = msm_bo->idx; 227d722e3fbSopenharmony_ci } else { 228d722e3fbSopenharmony_ci void *val; 229d722e3fbSopenharmony_ci 230d722e3fbSopenharmony_ci if (!msm_ring->bo_table) 231d722e3fbSopenharmony_ci msm_ring->bo_table = drmHashCreate(); 232d722e3fbSopenharmony_ci 233d722e3fbSopenharmony_ci if (!drmHashLookup(msm_ring->bo_table, bo->handle, &val)) { 234d722e3fbSopenharmony_ci /* found */ 235d722e3fbSopenharmony_ci idx = (uint32_t)(uintptr_t)val; 236d722e3fbSopenharmony_ci } else { 237d722e3fbSopenharmony_ci idx = append_bo(ring, bo); 238d722e3fbSopenharmony_ci val = (void *)(uintptr_t)idx; 239d722e3fbSopenharmony_ci drmHashInsert(msm_ring->bo_table, bo->handle, val); 240d722e3fbSopenharmony_ci } 241d722e3fbSopenharmony_ci msm_bo->current_ring_seqno = msm_ring->seqno; 242d722e3fbSopenharmony_ci msm_bo->idx = idx; 243d722e3fbSopenharmony_ci } 244d722e3fbSopenharmony_ci pthread_mutex_unlock(&idx_lock); 245d722e3fbSopenharmony_ci if (flags & FD_RELOC_READ) 246d722e3fbSopenharmony_ci msm_ring->submit.bos[idx].flags |= MSM_SUBMIT_BO_READ; 247d722e3fbSopenharmony_ci if (flags & FD_RELOC_WRITE) 248d722e3fbSopenharmony_ci msm_ring->submit.bos[idx].flags |= MSM_SUBMIT_BO_WRITE; 249d722e3fbSopenharmony_ci return idx; 250d722e3fbSopenharmony_ci} 251d722e3fbSopenharmony_ci 252d722e3fbSopenharmony_ci/* Ensure that submit has corresponding entry in cmds table for the 253d722e3fbSopenharmony_ci * target cmdstream buffer: 254d722e3fbSopenharmony_ci * 255d722e3fbSopenharmony_ci * Returns TRUE if new cmd added (else FALSE if it was already in 256d722e3fbSopenharmony_ci * the cmds table) 257d722e3fbSopenharmony_ci */ 258d722e3fbSopenharmony_cistatic int get_cmd(struct fd_ringbuffer *ring, struct msm_cmd *target_cmd, 259d722e3fbSopenharmony_ci uint32_t submit_offset, uint32_t size, uint32_t type) 260d722e3fbSopenharmony_ci{ 261d722e3fbSopenharmony_ci struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); 262d722e3fbSopenharmony_ci struct drm_msm_gem_submit_cmd *cmd; 263d722e3fbSopenharmony_ci uint32_t i; 264d722e3fbSopenharmony_ci void *val; 265d722e3fbSopenharmony_ci 266d722e3fbSopenharmony_ci if (!msm_ring->cmd_table) 267d722e3fbSopenharmony_ci msm_ring->cmd_table = drmHashCreate(); 268d722e3fbSopenharmony_ci 269d722e3fbSopenharmony_ci /* figure out if we already have a cmd buf.. short-circuit hash 270d722e3fbSopenharmony_ci * lookup if: 271d722e3fbSopenharmony_ci * - target cmd has never been added to submit.cmds 272d722e3fbSopenharmony_ci * - target cmd is not a streaming stateobj (which unlike longer 273d722e3fbSopenharmony_ci * lived CSO stateobj, is not expected to be reused with multiple 274d722e3fbSopenharmony_ci * submits) 275d722e3fbSopenharmony_ci */ 276d722e3fbSopenharmony_ci if (target_cmd->is_appended_to_submit && 277d722e3fbSopenharmony_ci !(target_cmd->ring->flags & FD_RINGBUFFER_STREAMING) && 278d722e3fbSopenharmony_ci !drmHashLookup(msm_ring->cmd_table, (unsigned long)target_cmd, &val)) { 279d722e3fbSopenharmony_ci i = VOID2U64(val); 280d722e3fbSopenharmony_ci cmd = &msm_ring->submit.cmds[i]; 281d722e3fbSopenharmony_ci 282d722e3fbSopenharmony_ci assert(cmd->submit_offset == submit_offset); 283d722e3fbSopenharmony_ci assert(cmd->size == size); 284d722e3fbSopenharmony_ci assert(cmd->type == type); 285d722e3fbSopenharmony_ci assert(msm_ring->submit.bos[cmd->submit_idx].handle == 286d722e3fbSopenharmony_ci target_cmd->ring_bo->handle); 287d722e3fbSopenharmony_ci 288d722e3fbSopenharmony_ci return FALSE; 289d722e3fbSopenharmony_ci } 290d722e3fbSopenharmony_ci 291d722e3fbSopenharmony_ci /* create cmd buf if not: */ 292d722e3fbSopenharmony_ci i = APPEND(&msm_ring->submit, cmds); 293d722e3fbSopenharmony_ci APPEND(msm_ring, cmds); 294d722e3fbSopenharmony_ci msm_ring->cmds[i] = target_cmd; 295d722e3fbSopenharmony_ci cmd = &msm_ring->submit.cmds[i]; 296d722e3fbSopenharmony_ci cmd->type = type; 297d722e3fbSopenharmony_ci cmd->submit_idx = bo2idx(ring, target_cmd->ring_bo, FD_RELOC_READ); 298d722e3fbSopenharmony_ci cmd->submit_offset = submit_offset; 299d722e3fbSopenharmony_ci cmd->size = size; 300d722e3fbSopenharmony_ci cmd->pad = 0; 301d722e3fbSopenharmony_ci 302d722e3fbSopenharmony_ci target_cmd->is_appended_to_submit = TRUE; 303d722e3fbSopenharmony_ci 304d722e3fbSopenharmony_ci if (!(target_cmd->ring->flags & FD_RINGBUFFER_STREAMING)) { 305d722e3fbSopenharmony_ci drmHashInsert(msm_ring->cmd_table, (unsigned long)target_cmd, 306d722e3fbSopenharmony_ci U642VOID(i)); 307d722e3fbSopenharmony_ci } 308d722e3fbSopenharmony_ci 309d722e3fbSopenharmony_ci target_cmd->size = size; 310d722e3fbSopenharmony_ci 311d722e3fbSopenharmony_ci return TRUE; 312d722e3fbSopenharmony_ci} 313d722e3fbSopenharmony_ci 314d722e3fbSopenharmony_cistatic void * msm_ringbuffer_hostptr(struct fd_ringbuffer *ring) 315d722e3fbSopenharmony_ci{ 316d722e3fbSopenharmony_ci struct msm_cmd *cmd = current_cmd(ring); 317d722e3fbSopenharmony_ci uint8_t *base = fd_bo_map(cmd->ring_bo); 318d722e3fbSopenharmony_ci return base + to_msm_ringbuffer(ring)->offset; 319d722e3fbSopenharmony_ci} 320d722e3fbSopenharmony_ci 321d722e3fbSopenharmony_cistatic void delete_cmds(struct msm_ringbuffer *msm_ring) 322d722e3fbSopenharmony_ci{ 323d722e3fbSopenharmony_ci struct msm_cmd *cmd, *tmp; 324d722e3fbSopenharmony_ci 325d722e3fbSopenharmony_ci LIST_FOR_EACH_ENTRY_SAFE(cmd, tmp, &msm_ring->cmd_list, list) { 326d722e3fbSopenharmony_ci ring_cmd_del(cmd); 327d722e3fbSopenharmony_ci } 328d722e3fbSopenharmony_ci} 329d722e3fbSopenharmony_ci 330d722e3fbSopenharmony_cistatic void flush_reset(struct fd_ringbuffer *ring) 331d722e3fbSopenharmony_ci{ 332d722e3fbSopenharmony_ci struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); 333d722e3fbSopenharmony_ci unsigned i; 334d722e3fbSopenharmony_ci 335d722e3fbSopenharmony_ci for (i = 0; i < msm_ring->nr_bos; i++) { 336d722e3fbSopenharmony_ci struct msm_bo *msm_bo = to_msm_bo(msm_ring->bos[i]); 337d722e3fbSopenharmony_ci if (!msm_bo) 338d722e3fbSopenharmony_ci continue; 339d722e3fbSopenharmony_ci msm_bo->current_ring_seqno = 0; 340d722e3fbSopenharmony_ci fd_bo_del(&msm_bo->base); 341d722e3fbSopenharmony_ci } 342d722e3fbSopenharmony_ci 343d722e3fbSopenharmony_ci for (i = 0; i < msm_ring->nr_cmds; i++) { 344d722e3fbSopenharmony_ci struct msm_cmd *msm_cmd = msm_ring->cmds[i]; 345d722e3fbSopenharmony_ci 346d722e3fbSopenharmony_ci if (msm_cmd->ring == ring) 347d722e3fbSopenharmony_ci continue; 348d722e3fbSopenharmony_ci 349d722e3fbSopenharmony_ci if (msm_cmd->ring->flags & FD_RINGBUFFER_OBJECT) 350d722e3fbSopenharmony_ci fd_ringbuffer_del(msm_cmd->ring); 351d722e3fbSopenharmony_ci } 352d722e3fbSopenharmony_ci 353d722e3fbSopenharmony_ci msm_ring->submit.nr_cmds = 0; 354d722e3fbSopenharmony_ci msm_ring->submit.nr_bos = 0; 355d722e3fbSopenharmony_ci msm_ring->nr_cmds = 0; 356d722e3fbSopenharmony_ci msm_ring->nr_bos = 0; 357d722e3fbSopenharmony_ci 358d722e3fbSopenharmony_ci if (msm_ring->bo_table) { 359d722e3fbSopenharmony_ci drmHashDestroy(msm_ring->bo_table); 360d722e3fbSopenharmony_ci msm_ring->bo_table = NULL; 361d722e3fbSopenharmony_ci } 362d722e3fbSopenharmony_ci 363d722e3fbSopenharmony_ci if (msm_ring->cmd_table) { 364d722e3fbSopenharmony_ci drmHashDestroy(msm_ring->cmd_table); 365d722e3fbSopenharmony_ci msm_ring->cmd_table = NULL; 366d722e3fbSopenharmony_ci } 367d722e3fbSopenharmony_ci 368d722e3fbSopenharmony_ci if (msm_ring->is_growable) { 369d722e3fbSopenharmony_ci delete_cmds(msm_ring); 370d722e3fbSopenharmony_ci } else { 371d722e3fbSopenharmony_ci /* in old mode, just reset the # of relocs: */ 372d722e3fbSopenharmony_ci current_cmd(ring)->nr_relocs = 0; 373d722e3fbSopenharmony_ci } 374d722e3fbSopenharmony_ci} 375d722e3fbSopenharmony_ci 376d722e3fbSopenharmony_cistatic void finalize_current_cmd(struct fd_ringbuffer *ring, uint32_t *last_start) 377d722e3fbSopenharmony_ci{ 378d722e3fbSopenharmony_ci uint32_t submit_offset, size, type; 379d722e3fbSopenharmony_ci struct fd_ringbuffer *parent; 380d722e3fbSopenharmony_ci 381d722e3fbSopenharmony_ci if (ring->parent) { 382d722e3fbSopenharmony_ci parent = ring->parent; 383d722e3fbSopenharmony_ci type = MSM_SUBMIT_CMD_IB_TARGET_BUF; 384d722e3fbSopenharmony_ci } else { 385d722e3fbSopenharmony_ci parent = ring; 386d722e3fbSopenharmony_ci type = MSM_SUBMIT_CMD_BUF; 387d722e3fbSopenharmony_ci } 388d722e3fbSopenharmony_ci 389d722e3fbSopenharmony_ci submit_offset = offset_bytes(last_start, ring->start); 390d722e3fbSopenharmony_ci size = offset_bytes(ring->cur, last_start); 391d722e3fbSopenharmony_ci 392d722e3fbSopenharmony_ci get_cmd(parent, current_cmd(ring), submit_offset, size, type); 393d722e3fbSopenharmony_ci} 394d722e3fbSopenharmony_ci 395d722e3fbSopenharmony_cistatic void dump_submit(struct msm_ringbuffer *msm_ring) 396d722e3fbSopenharmony_ci{ 397d722e3fbSopenharmony_ci uint32_t i, j; 398d722e3fbSopenharmony_ci 399d722e3fbSopenharmony_ci for (i = 0; i < msm_ring->submit.nr_bos; i++) { 400d722e3fbSopenharmony_ci struct drm_msm_gem_submit_bo *bo = &msm_ring->submit.bos[i]; 401d722e3fbSopenharmony_ci ERROR_MSG(" bos[%d]: handle=%u, flags=%x", i, bo->handle, bo->flags); 402d722e3fbSopenharmony_ci } 403d722e3fbSopenharmony_ci for (i = 0; i < msm_ring->submit.nr_cmds; i++) { 404d722e3fbSopenharmony_ci struct drm_msm_gem_submit_cmd *cmd = &msm_ring->submit.cmds[i]; 405d722e3fbSopenharmony_ci struct drm_msm_gem_submit_reloc *relocs = U642VOID(cmd->relocs); 406d722e3fbSopenharmony_ci ERROR_MSG(" cmd[%d]: type=%u, submit_idx=%u, submit_offset=%u, size=%u", 407d722e3fbSopenharmony_ci i, cmd->type, cmd->submit_idx, cmd->submit_offset, cmd->size); 408d722e3fbSopenharmony_ci for (j = 0; j < cmd->nr_relocs; j++) { 409d722e3fbSopenharmony_ci struct drm_msm_gem_submit_reloc *r = &relocs[j]; 410d722e3fbSopenharmony_ci ERROR_MSG(" reloc[%d]: submit_offset=%u, or=%08x, shift=%d, reloc_idx=%u" 411d722e3fbSopenharmony_ci ", reloc_offset=%"PRIu64, j, r->submit_offset, r->or, r->shift, 412d722e3fbSopenharmony_ci r->reloc_idx, r->reloc_offset); 413d722e3fbSopenharmony_ci } 414d722e3fbSopenharmony_ci } 415d722e3fbSopenharmony_ci} 416d722e3fbSopenharmony_ci 417d722e3fbSopenharmony_cistatic struct drm_msm_gem_submit_reloc * 418d722e3fbSopenharmony_cihandle_stateobj_relocs(struct fd_ringbuffer *parent, struct fd_ringbuffer *stateobj, 419d722e3fbSopenharmony_ci struct drm_msm_gem_submit_reloc *orig_relocs, unsigned nr_relocs) 420d722e3fbSopenharmony_ci{ 421d722e3fbSopenharmony_ci struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(stateobj); 422d722e3fbSopenharmony_ci struct drm_msm_gem_submit_reloc *relocs = malloc(nr_relocs * sizeof(*relocs)); 423d722e3fbSopenharmony_ci unsigned i; 424d722e3fbSopenharmony_ci 425d722e3fbSopenharmony_ci for (i = 0; i < nr_relocs; i++) { 426d722e3fbSopenharmony_ci unsigned idx = orig_relocs[i].reloc_idx; 427d722e3fbSopenharmony_ci struct fd_bo *bo = msm_ring->bos[idx]; 428d722e3fbSopenharmony_ci unsigned flags = 0; 429d722e3fbSopenharmony_ci 430d722e3fbSopenharmony_ci if (msm_ring->submit.bos[idx].flags & MSM_SUBMIT_BO_READ) 431d722e3fbSopenharmony_ci flags |= FD_RELOC_READ; 432d722e3fbSopenharmony_ci if (msm_ring->submit.bos[idx].flags & MSM_SUBMIT_BO_WRITE) 433d722e3fbSopenharmony_ci flags |= FD_RELOC_WRITE; 434d722e3fbSopenharmony_ci 435d722e3fbSopenharmony_ci relocs[i] = orig_relocs[i]; 436d722e3fbSopenharmony_ci relocs[i].reloc_idx = bo2idx(parent, bo, flags); 437d722e3fbSopenharmony_ci } 438d722e3fbSopenharmony_ci 439d722e3fbSopenharmony_ci /* stateobj rb's could have reloc's to other stateobj rb's which didn't 440d722e3fbSopenharmony_ci * get propagated to the parent rb at _emit_reloc_ring() time (because 441d722e3fbSopenharmony_ci * the parent wasn't known then), so fix that up now: 442d722e3fbSopenharmony_ci */ 443d722e3fbSopenharmony_ci for (i = 0; i < msm_ring->nr_cmds; i++) { 444d722e3fbSopenharmony_ci struct msm_cmd *msm_cmd = msm_ring->cmds[i]; 445d722e3fbSopenharmony_ci struct drm_msm_gem_submit_cmd *cmd = &msm_ring->submit.cmds[i]; 446d722e3fbSopenharmony_ci 447d722e3fbSopenharmony_ci if (msm_ring->cmds[i]->ring == stateobj) 448d722e3fbSopenharmony_ci continue; 449d722e3fbSopenharmony_ci 450d722e3fbSopenharmony_ci assert(msm_cmd->ring->flags & FD_RINGBUFFER_OBJECT); 451d722e3fbSopenharmony_ci 452d722e3fbSopenharmony_ci if (get_cmd(parent, msm_cmd, cmd->submit_offset, cmd->size, cmd->type)) { 453d722e3fbSopenharmony_ci fd_ringbuffer_ref(msm_cmd->ring); 454d722e3fbSopenharmony_ci } 455d722e3fbSopenharmony_ci } 456d722e3fbSopenharmony_ci 457d722e3fbSopenharmony_ci return relocs; 458d722e3fbSopenharmony_ci} 459d722e3fbSopenharmony_ci 460d722e3fbSopenharmony_cistatic int msm_ringbuffer_flush(struct fd_ringbuffer *ring, uint32_t *last_start, 461d722e3fbSopenharmony_ci int in_fence_fd, int *out_fence_fd) 462d722e3fbSopenharmony_ci{ 463d722e3fbSopenharmony_ci struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); 464d722e3fbSopenharmony_ci struct msm_pipe *msm_pipe = to_msm_pipe(ring->pipe); 465d722e3fbSopenharmony_ci struct drm_msm_gem_submit req = { 466d722e3fbSopenharmony_ci .flags = msm_pipe->pipe, 467d722e3fbSopenharmony_ci .queueid = msm_pipe->queue_id, 468d722e3fbSopenharmony_ci }; 469d722e3fbSopenharmony_ci uint32_t i; 470d722e3fbSopenharmony_ci int ret; 471d722e3fbSopenharmony_ci 472d722e3fbSopenharmony_ci assert(!ring->parent); 473d722e3fbSopenharmony_ci 474d722e3fbSopenharmony_ci if (in_fence_fd != -1) { 475d722e3fbSopenharmony_ci req.flags |= MSM_SUBMIT_FENCE_FD_IN | MSM_SUBMIT_NO_IMPLICIT; 476d722e3fbSopenharmony_ci req.fence_fd = in_fence_fd; 477d722e3fbSopenharmony_ci } 478d722e3fbSopenharmony_ci 479d722e3fbSopenharmony_ci if (out_fence_fd) { 480d722e3fbSopenharmony_ci req.flags |= MSM_SUBMIT_FENCE_FD_OUT; 481d722e3fbSopenharmony_ci } 482d722e3fbSopenharmony_ci 483d722e3fbSopenharmony_ci finalize_current_cmd(ring, last_start); 484d722e3fbSopenharmony_ci 485d722e3fbSopenharmony_ci /* for each of the cmd's fix up their reloc's: */ 486d722e3fbSopenharmony_ci for (i = 0; i < msm_ring->submit.nr_cmds; i++) { 487d722e3fbSopenharmony_ci struct msm_cmd *msm_cmd = msm_ring->cmds[i]; 488d722e3fbSopenharmony_ci struct drm_msm_gem_submit_reloc *relocs = msm_cmd->relocs; 489d722e3fbSopenharmony_ci struct drm_msm_gem_submit_cmd *cmd; 490d722e3fbSopenharmony_ci unsigned nr_relocs = msm_cmd->nr_relocs; 491d722e3fbSopenharmony_ci 492d722e3fbSopenharmony_ci /* for reusable stateobjs, the reloc table has reloc_idx that 493d722e3fbSopenharmony_ci * points into it's own private bos table, rather than the global 494d722e3fbSopenharmony_ci * bos table used for the submit, so we need to add the stateobj's 495d722e3fbSopenharmony_ci * bos to the global table and construct new relocs table with 496d722e3fbSopenharmony_ci * corresponding reloc_idx 497d722e3fbSopenharmony_ci */ 498d722e3fbSopenharmony_ci if (msm_cmd->ring->flags & FD_RINGBUFFER_OBJECT) { 499d722e3fbSopenharmony_ci relocs = handle_stateobj_relocs(ring, msm_cmd->ring, 500d722e3fbSopenharmony_ci relocs, nr_relocs); 501d722e3fbSopenharmony_ci } 502d722e3fbSopenharmony_ci 503d722e3fbSopenharmony_ci cmd = &msm_ring->submit.cmds[i]; 504d722e3fbSopenharmony_ci cmd->relocs = VOID2U64(relocs); 505d722e3fbSopenharmony_ci cmd->nr_relocs = nr_relocs; 506d722e3fbSopenharmony_ci } 507d722e3fbSopenharmony_ci 508d722e3fbSopenharmony_ci /* needs to be after get_cmd() as that could create bos/cmds table: */ 509d722e3fbSopenharmony_ci req.bos = VOID2U64(msm_ring->submit.bos), 510d722e3fbSopenharmony_ci req.nr_bos = msm_ring->submit.nr_bos; 511d722e3fbSopenharmony_ci req.cmds = VOID2U64(msm_ring->submit.cmds), 512d722e3fbSopenharmony_ci req.nr_cmds = msm_ring->submit.nr_cmds; 513d722e3fbSopenharmony_ci 514d722e3fbSopenharmony_ci DEBUG_MSG("nr_cmds=%u, nr_bos=%u", req.nr_cmds, req.nr_bos); 515d722e3fbSopenharmony_ci 516d722e3fbSopenharmony_ci ret = drmCommandWriteRead(ring->pipe->dev->fd, DRM_MSM_GEM_SUBMIT, 517d722e3fbSopenharmony_ci &req, sizeof(req)); 518d722e3fbSopenharmony_ci if (ret) { 519d722e3fbSopenharmony_ci ERROR_MSG("submit failed: %d (%s)", ret, strerror(errno)); 520d722e3fbSopenharmony_ci dump_submit(msm_ring); 521d722e3fbSopenharmony_ci } else if (!ret) { 522d722e3fbSopenharmony_ci /* update timestamp on all rings associated with submit: */ 523d722e3fbSopenharmony_ci for (i = 0; i < msm_ring->submit.nr_cmds; i++) { 524d722e3fbSopenharmony_ci struct msm_cmd *msm_cmd = msm_ring->cmds[i]; 525d722e3fbSopenharmony_ci msm_cmd->ring->last_timestamp = req.fence; 526d722e3fbSopenharmony_ci } 527d722e3fbSopenharmony_ci 528d722e3fbSopenharmony_ci if (out_fence_fd) { 529d722e3fbSopenharmony_ci *out_fence_fd = req.fence_fd; 530d722e3fbSopenharmony_ci } 531d722e3fbSopenharmony_ci } 532d722e3fbSopenharmony_ci 533d722e3fbSopenharmony_ci /* free dynamically constructed stateobj relocs tables: */ 534d722e3fbSopenharmony_ci for (i = 0; i < msm_ring->submit.nr_cmds; i++) { 535d722e3fbSopenharmony_ci struct drm_msm_gem_submit_cmd *cmd = &msm_ring->submit.cmds[i]; 536d722e3fbSopenharmony_ci struct msm_cmd *msm_cmd = msm_ring->cmds[i]; 537d722e3fbSopenharmony_ci if (msm_cmd->ring->flags & FD_RINGBUFFER_OBJECT) { 538d722e3fbSopenharmony_ci free(U642VOID(cmd->relocs)); 539d722e3fbSopenharmony_ci } 540d722e3fbSopenharmony_ci } 541d722e3fbSopenharmony_ci 542d722e3fbSopenharmony_ci flush_reset(ring); 543d722e3fbSopenharmony_ci 544d722e3fbSopenharmony_ci return ret; 545d722e3fbSopenharmony_ci} 546d722e3fbSopenharmony_ci 547d722e3fbSopenharmony_cistatic void msm_ringbuffer_grow(struct fd_ringbuffer *ring, uint32_t size) 548d722e3fbSopenharmony_ci{ 549d722e3fbSopenharmony_ci assert(to_msm_ringbuffer(ring)->is_growable); 550d722e3fbSopenharmony_ci finalize_current_cmd(ring, ring->last_start); 551d722e3fbSopenharmony_ci ring_cmd_new(ring, size, 0); 552d722e3fbSopenharmony_ci} 553d722e3fbSopenharmony_ci 554d722e3fbSopenharmony_cistatic void msm_ringbuffer_reset(struct fd_ringbuffer *ring) 555d722e3fbSopenharmony_ci{ 556d722e3fbSopenharmony_ci flush_reset(ring); 557d722e3fbSopenharmony_ci} 558d722e3fbSopenharmony_ci 559d722e3fbSopenharmony_cistatic void msm_ringbuffer_emit_reloc(struct fd_ringbuffer *ring, 560d722e3fbSopenharmony_ci const struct fd_reloc *r) 561d722e3fbSopenharmony_ci{ 562d722e3fbSopenharmony_ci struct fd_ringbuffer *parent = ring->parent ? ring->parent : ring; 563d722e3fbSopenharmony_ci struct msm_bo *msm_bo = to_msm_bo(r->bo); 564d722e3fbSopenharmony_ci struct drm_msm_gem_submit_reloc *reloc; 565d722e3fbSopenharmony_ci struct msm_cmd *cmd = current_cmd(ring); 566d722e3fbSopenharmony_ci uint32_t idx = APPEND(cmd, relocs); 567d722e3fbSopenharmony_ci uint32_t addr; 568d722e3fbSopenharmony_ci 569d722e3fbSopenharmony_ci reloc = &cmd->relocs[idx]; 570d722e3fbSopenharmony_ci 571d722e3fbSopenharmony_ci reloc->reloc_idx = bo2idx(parent, r->bo, r->flags); 572d722e3fbSopenharmony_ci reloc->reloc_offset = r->offset; 573d722e3fbSopenharmony_ci reloc->or = r->or; 574d722e3fbSopenharmony_ci reloc->shift = r->shift; 575d722e3fbSopenharmony_ci reloc->submit_offset = offset_bytes(ring->cur, ring->start) + 576d722e3fbSopenharmony_ci to_msm_ringbuffer(ring)->offset; 577d722e3fbSopenharmony_ci 578d722e3fbSopenharmony_ci addr = msm_bo->presumed; 579d722e3fbSopenharmony_ci if (reloc->shift < 0) 580d722e3fbSopenharmony_ci addr >>= -reloc->shift; 581d722e3fbSopenharmony_ci else 582d722e3fbSopenharmony_ci addr <<= reloc->shift; 583d722e3fbSopenharmony_ci (*ring->cur++) = addr | r->or; 584d722e3fbSopenharmony_ci 585d722e3fbSopenharmony_ci if (ring->pipe->gpu_id >= 500) { 586d722e3fbSopenharmony_ci struct drm_msm_gem_submit_reloc *reloc_hi; 587d722e3fbSopenharmony_ci 588d722e3fbSopenharmony_ci /* NOTE: grab reloc_idx *before* APPEND() since that could 589d722e3fbSopenharmony_ci * realloc() meaning that 'reloc' ptr is no longer valid: 590d722e3fbSopenharmony_ci */ 591d722e3fbSopenharmony_ci uint32_t reloc_idx = reloc->reloc_idx; 592d722e3fbSopenharmony_ci 593d722e3fbSopenharmony_ci idx = APPEND(cmd, relocs); 594d722e3fbSopenharmony_ci 595d722e3fbSopenharmony_ci reloc_hi = &cmd->relocs[idx]; 596d722e3fbSopenharmony_ci 597d722e3fbSopenharmony_ci reloc_hi->reloc_idx = reloc_idx; 598d722e3fbSopenharmony_ci reloc_hi->reloc_offset = r->offset; 599d722e3fbSopenharmony_ci reloc_hi->or = r->orhi; 600d722e3fbSopenharmony_ci reloc_hi->shift = r->shift - 32; 601d722e3fbSopenharmony_ci reloc_hi->submit_offset = offset_bytes(ring->cur, ring->start) + 602d722e3fbSopenharmony_ci to_msm_ringbuffer(ring)->offset; 603d722e3fbSopenharmony_ci 604d722e3fbSopenharmony_ci addr = msm_bo->presumed >> 32; 605d722e3fbSopenharmony_ci if (reloc_hi->shift < 0) 606d722e3fbSopenharmony_ci addr >>= -reloc_hi->shift; 607d722e3fbSopenharmony_ci else 608d722e3fbSopenharmony_ci addr <<= reloc_hi->shift; 609d722e3fbSopenharmony_ci (*ring->cur++) = addr | r->orhi; 610d722e3fbSopenharmony_ci } 611d722e3fbSopenharmony_ci} 612d722e3fbSopenharmony_ci 613d722e3fbSopenharmony_cistatic uint32_t msm_ringbuffer_emit_reloc_ring(struct fd_ringbuffer *ring, 614d722e3fbSopenharmony_ci struct fd_ringbuffer *target, uint32_t cmd_idx) 615d722e3fbSopenharmony_ci{ 616d722e3fbSopenharmony_ci struct msm_cmd *cmd = NULL; 617d722e3fbSopenharmony_ci struct msm_ringbuffer *msm_target = to_msm_ringbuffer(target); 618d722e3fbSopenharmony_ci uint32_t idx = 0; 619d722e3fbSopenharmony_ci int added_cmd = FALSE; 620d722e3fbSopenharmony_ci uint32_t size; 621d722e3fbSopenharmony_ci uint32_t submit_offset = msm_target->offset; 622d722e3fbSopenharmony_ci 623d722e3fbSopenharmony_ci LIST_FOR_EACH_ENTRY(cmd, &msm_target->cmd_list, list) { 624d722e3fbSopenharmony_ci if (idx == cmd_idx) 625d722e3fbSopenharmony_ci break; 626d722e3fbSopenharmony_ci idx++; 627d722e3fbSopenharmony_ci } 628d722e3fbSopenharmony_ci 629d722e3fbSopenharmony_ci assert(cmd && (idx == cmd_idx)); 630d722e3fbSopenharmony_ci 631d722e3fbSopenharmony_ci if (idx < (msm_target->cmd_count - 1)) { 632d722e3fbSopenharmony_ci /* All but the last cmd buffer is fully "baked" (ie. already has 633d722e3fbSopenharmony_ci * done get_cmd() to add it to the cmds table). But in this case, 634d722e3fbSopenharmony_ci * the size we get is invalid (since it is calculated from the 635d722e3fbSopenharmony_ci * last cmd buffer): 636d722e3fbSopenharmony_ci */ 637d722e3fbSopenharmony_ci size = cmd->size; 638d722e3fbSopenharmony_ci } else { 639d722e3fbSopenharmony_ci struct fd_ringbuffer *parent = ring->parent ? ring->parent : ring; 640d722e3fbSopenharmony_ci size = offset_bytes(target->cur, target->start); 641d722e3fbSopenharmony_ci added_cmd = get_cmd(parent, cmd, submit_offset, size, 642d722e3fbSopenharmony_ci MSM_SUBMIT_CMD_IB_TARGET_BUF); 643d722e3fbSopenharmony_ci } 644d722e3fbSopenharmony_ci 645d722e3fbSopenharmony_ci msm_ringbuffer_emit_reloc(ring, &(struct fd_reloc){ 646d722e3fbSopenharmony_ci .bo = cmd->ring_bo, 647d722e3fbSopenharmony_ci .flags = FD_RELOC_READ, 648d722e3fbSopenharmony_ci .offset = submit_offset, 649d722e3fbSopenharmony_ci }); 650d722e3fbSopenharmony_ci 651d722e3fbSopenharmony_ci /* Unlike traditional ringbuffers which are deleted as a set (after 652d722e3fbSopenharmony_ci * being flushed), mesa can't really guarantee that a stateobj isn't 653d722e3fbSopenharmony_ci * destroyed after emitted but before flush, so we must hold a ref: 654d722e3fbSopenharmony_ci */ 655d722e3fbSopenharmony_ci if (added_cmd && (target->flags & FD_RINGBUFFER_OBJECT)) { 656d722e3fbSopenharmony_ci fd_ringbuffer_ref(target); 657d722e3fbSopenharmony_ci } 658d722e3fbSopenharmony_ci 659d722e3fbSopenharmony_ci return size; 660d722e3fbSopenharmony_ci} 661d722e3fbSopenharmony_ci 662d722e3fbSopenharmony_cistatic uint32_t msm_ringbuffer_cmd_count(struct fd_ringbuffer *ring) 663d722e3fbSopenharmony_ci{ 664d722e3fbSopenharmony_ci return to_msm_ringbuffer(ring)->cmd_count; 665d722e3fbSopenharmony_ci} 666d722e3fbSopenharmony_ci 667d722e3fbSopenharmony_cistatic void msm_ringbuffer_destroy(struct fd_ringbuffer *ring) 668d722e3fbSopenharmony_ci{ 669d722e3fbSopenharmony_ci struct msm_ringbuffer *msm_ring = to_msm_ringbuffer(ring); 670d722e3fbSopenharmony_ci 671d722e3fbSopenharmony_ci flush_reset(ring); 672d722e3fbSopenharmony_ci delete_cmds(msm_ring); 673d722e3fbSopenharmony_ci 674d722e3fbSopenharmony_ci free(msm_ring->submit.cmds); 675d722e3fbSopenharmony_ci free(msm_ring->submit.bos); 676d722e3fbSopenharmony_ci free(msm_ring->bos); 677d722e3fbSopenharmony_ci free(msm_ring->cmds); 678d722e3fbSopenharmony_ci free(msm_ring); 679d722e3fbSopenharmony_ci} 680d722e3fbSopenharmony_ci 681d722e3fbSopenharmony_cistatic const struct fd_ringbuffer_funcs funcs = { 682d722e3fbSopenharmony_ci .hostptr = msm_ringbuffer_hostptr, 683d722e3fbSopenharmony_ci .flush = msm_ringbuffer_flush, 684d722e3fbSopenharmony_ci .grow = msm_ringbuffer_grow, 685d722e3fbSopenharmony_ci .reset = msm_ringbuffer_reset, 686d722e3fbSopenharmony_ci .emit_reloc = msm_ringbuffer_emit_reloc, 687d722e3fbSopenharmony_ci .emit_reloc_ring = msm_ringbuffer_emit_reloc_ring, 688d722e3fbSopenharmony_ci .cmd_count = msm_ringbuffer_cmd_count, 689d722e3fbSopenharmony_ci .destroy = msm_ringbuffer_destroy, 690d722e3fbSopenharmony_ci}; 691d722e3fbSopenharmony_ci 692d722e3fbSopenharmony_cidrm_private struct fd_ringbuffer * msm_ringbuffer_new(struct fd_pipe *pipe, 693d722e3fbSopenharmony_ci uint32_t size, enum fd_ringbuffer_flags flags) 694d722e3fbSopenharmony_ci{ 695d722e3fbSopenharmony_ci struct msm_ringbuffer *msm_ring; 696d722e3fbSopenharmony_ci struct fd_ringbuffer *ring; 697d722e3fbSopenharmony_ci 698d722e3fbSopenharmony_ci msm_ring = calloc(1, sizeof(*msm_ring)); 699d722e3fbSopenharmony_ci if (!msm_ring) { 700d722e3fbSopenharmony_ci ERROR_MSG("allocation failed"); 701d722e3fbSopenharmony_ci return NULL; 702d722e3fbSopenharmony_ci } 703d722e3fbSopenharmony_ci 704d722e3fbSopenharmony_ci if (size == 0) { 705d722e3fbSopenharmony_ci assert(pipe->dev->version >= FD_VERSION_UNLIMITED_CMDS); 706d722e3fbSopenharmony_ci size = INIT_SIZE; 707d722e3fbSopenharmony_ci msm_ring->is_growable = TRUE; 708d722e3fbSopenharmony_ci } 709d722e3fbSopenharmony_ci 710d722e3fbSopenharmony_ci list_inithead(&msm_ring->cmd_list); 711d722e3fbSopenharmony_ci msm_ring->seqno = ++to_msm_device(pipe->dev)->ring_cnt; 712d722e3fbSopenharmony_ci 713d722e3fbSopenharmony_ci ring = &msm_ring->base; 714d722e3fbSopenharmony_ci atomic_set(&ring->refcnt, 1); 715d722e3fbSopenharmony_ci 716d722e3fbSopenharmony_ci ring->funcs = &funcs; 717d722e3fbSopenharmony_ci ring->size = size; 718d722e3fbSopenharmony_ci ring->pipe = pipe; /* needed in ring_cmd_new() */ 719d722e3fbSopenharmony_ci 720d722e3fbSopenharmony_ci ring_cmd_new(ring, size, flags); 721d722e3fbSopenharmony_ci 722d722e3fbSopenharmony_ci return ring; 723d722e3fbSopenharmony_ci} 724