1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2021 Google LLC 3bf215546Sopenharmony_ci * SPDX-License-Identifier: MIT 4bf215546Sopenharmony_ci */ 5bf215546Sopenharmony_ci 6bf215546Sopenharmony_ci#ifndef VN_RING_H 7bf215546Sopenharmony_ci#define VN_RING_H 8bf215546Sopenharmony_ci 9bf215546Sopenharmony_ci#include "vn_common.h" 10bf215546Sopenharmony_ci 11bf215546Sopenharmony_ci/** 12bf215546Sopenharmony_ci * A ring is a single-producer and single-consumer circular buffer. The data 13bf215546Sopenharmony_ci * in the buffer are produced and consumed in order. An externally-defined 14bf215546Sopenharmony_ci * mechanism is required for ring setup and notifications in both directions. 15bf215546Sopenharmony_ci * Notifications for new data from the producer are needed only when the 16bf215546Sopenharmony_ci * consumer is not actively polling, which is indicated by the ring status. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * For venus, the data are plain venus commands. When a venus command is 19bf215546Sopenharmony_ci * consumed from the ring's perspective, there can still be ongoing CPU and/or 20bf215546Sopenharmony_ci * GPU works. This is not an issue when the works generated by following 21bf215546Sopenharmony_ci * venus commands are correctly queued after the ongoing works. There are 22bf215546Sopenharmony_ci * also venus commands that facilitate polling or waiting for ongoing works. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci/* the layout of a ring in a shmem */ 26bf215546Sopenharmony_cistruct vn_ring_layout { 27bf215546Sopenharmony_ci size_t head_offset; 28bf215546Sopenharmony_ci size_t tail_offset; 29bf215546Sopenharmony_ci size_t status_offset; 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci size_t buffer_offset; 32bf215546Sopenharmony_ci size_t buffer_size; 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci size_t extra_offset; 35bf215546Sopenharmony_ci size_t extra_size; 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci size_t shmem_size; 38bf215546Sopenharmony_ci}; 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_cistatic_assert(ATOMIC_INT_LOCK_FREE == 2 && sizeof(atomic_uint) == 4, 41bf215546Sopenharmony_ci "vn_ring_shared requires lock-free 32-bit atomic_uint"); 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci/* pointers to a ring in a BO */ 44bf215546Sopenharmony_cistruct vn_ring_shared { 45bf215546Sopenharmony_ci const volatile atomic_uint *head; 46bf215546Sopenharmony_ci volatile atomic_uint *tail; 47bf215546Sopenharmony_ci const volatile atomic_uint *status; 48bf215546Sopenharmony_ci void *buffer; 49bf215546Sopenharmony_ci void *extra; 50bf215546Sopenharmony_ci}; 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_cistruct vn_ring_submit { 53bf215546Sopenharmony_ci uint32_t seqno; 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci struct list_head head; 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci /* BOs to keep alive (TODO make sure shmems are pinned) */ 58bf215546Sopenharmony_ci uint32_t shmem_count; 59bf215546Sopenharmony_ci struct vn_renderer_shmem *shmems[]; 60bf215546Sopenharmony_ci}; 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_cistruct vn_ring { 63bf215546Sopenharmony_ci struct vn_renderer *renderer; 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci /* TODO assume large ring support and use fixed size */ 66bf215546Sopenharmony_ci uint32_t buffer_size; 67bf215546Sopenharmony_ci uint32_t buffer_mask; 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci struct vn_ring_shared shared; 70bf215546Sopenharmony_ci uint32_t cur; 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci struct list_head submits; 73bf215546Sopenharmony_ci struct list_head free_submits; 74bf215546Sopenharmony_ci}; 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_civoid 77bf215546Sopenharmony_civn_ring_get_layout(size_t buf_size, 78bf215546Sopenharmony_ci size_t extra_size, 79bf215546Sopenharmony_ci struct vn_ring_layout *layout); 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_civoid 82bf215546Sopenharmony_civn_ring_init(struct vn_ring *ring, 83bf215546Sopenharmony_ci struct vn_renderer *renderer, 84bf215546Sopenharmony_ci const struct vn_ring_layout *layout, 85bf215546Sopenharmony_ci void *shared); 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_civoid 88bf215546Sopenharmony_civn_ring_fini(struct vn_ring *ring); 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_cistruct vn_ring_submit * 91bf215546Sopenharmony_civn_ring_get_submit(struct vn_ring *ring, uint32_t shmem_count); 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_cibool 94bf215546Sopenharmony_civn_ring_submit(struct vn_ring *ring, 95bf215546Sopenharmony_ci struct vn_ring_submit *submit, 96bf215546Sopenharmony_ci const struct vn_cs_encoder *cs, 97bf215546Sopenharmony_ci uint32_t *seqno); 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_civoid 100bf215546Sopenharmony_civn_ring_wait(const struct vn_ring *ring, uint32_t seqno); 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_civoid 103bf215546Sopenharmony_civn_ring_wait_all(const struct vn_ring *ring); 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci#endif /* VN_RING_H */ 106