1*437bfbebSnyanmisaka /* SPDX-License-Identifier: Apache-2.0 OR MIT */ 2*437bfbebSnyanmisaka /* 3*437bfbebSnyanmisaka * Copyright (c) 2015 Rockchip Electronics Co., Ltd. 4*437bfbebSnyanmisaka */ 5*437bfbebSnyanmisaka 6*437bfbebSnyanmisaka #ifndef __MPP_BUFFER_IMPL_H__ 7*437bfbebSnyanmisaka #define __MPP_BUFFER_IMPL_H__ 8*437bfbebSnyanmisaka 9*437bfbebSnyanmisaka #include "mpp_list.h" 10*437bfbebSnyanmisaka #include "mpp_hash.h" 11*437bfbebSnyanmisaka #include "mpp_common.h" 12*437bfbebSnyanmisaka #include "mpp_allocator.h" 13*437bfbebSnyanmisaka #include "mpp_device.h" 14*437bfbebSnyanmisaka 15*437bfbebSnyanmisaka #define MPP_BUF_DBG_FUNCTION (0x00000001) 16*437bfbebSnyanmisaka #define MPP_BUF_DBG_OPS_RUNTIME (0x00000002) 17*437bfbebSnyanmisaka #define MPP_BUF_DBG_OPS_HISTORY (0x00000004) 18*437bfbebSnyanmisaka #define MPP_BUF_DBG_CLR_ON_EXIT (0x00000010) 19*437bfbebSnyanmisaka #define MPP_BUF_DBG_DUMP_ON_EXIT (0x00000020) 20*437bfbebSnyanmisaka #define MPP_BUF_DBG_CHECK_SIZE (0x00000100) 21*437bfbebSnyanmisaka 22*437bfbebSnyanmisaka #define mpp_buf_dbg(flag, fmt, ...) _mpp_dbg(mpp_buffer_debug, flag, fmt, ## __VA_ARGS__) 23*437bfbebSnyanmisaka #define mpp_buf_dbg_f(flag, fmt, ...) _mpp_dbg_f(mpp_buffer_debug, flag, fmt, ## __VA_ARGS__) 24*437bfbebSnyanmisaka 25*437bfbebSnyanmisaka #define MPP_BUF_FUNCTION_ENTER() mpp_buf_dbg_f(MPP_BUF_DBG_FUNCTION, "enter\n") 26*437bfbebSnyanmisaka #define MPP_BUF_FUNCTION_LEAVE() mpp_buf_dbg_f(MPP_BUF_DBG_FUNCTION, "leave\n") 27*437bfbebSnyanmisaka #define MPP_BUF_FUNCTION_LEAVE_OK() mpp_buf_dbg_f(MPP_BUF_DBG_FUNCTION, "success\n") 28*437bfbebSnyanmisaka #define MPP_BUF_FUNCTION_LEAVE_FAIL() mpp_buf_dbg_f(MPP_BUF_DBG_FUNCTION, "failed\n") 29*437bfbebSnyanmisaka 30*437bfbebSnyanmisaka typedef enum MppBufOps_e { 31*437bfbebSnyanmisaka GRP_CREATE, 32*437bfbebSnyanmisaka GRP_RELEASE, 33*437bfbebSnyanmisaka GRP_RESET, 34*437bfbebSnyanmisaka GRP_ORPHAN, 35*437bfbebSnyanmisaka GRP_DESTROY, 36*437bfbebSnyanmisaka 37*437bfbebSnyanmisaka GRP_OPS_BUTT = GRP_DESTROY, 38*437bfbebSnyanmisaka BUF_COMMIT, 39*437bfbebSnyanmisaka BUF_CREATE, 40*437bfbebSnyanmisaka BUF_MMAP, 41*437bfbebSnyanmisaka BUF_REF_INC, 42*437bfbebSnyanmisaka BUF_REF_DEC, 43*437bfbebSnyanmisaka BUF_DISCARD, 44*437bfbebSnyanmisaka BUF_DESTROY, 45*437bfbebSnyanmisaka BUF_OPS_BUTT, 46*437bfbebSnyanmisaka } MppBufOps; 47*437bfbebSnyanmisaka 48*437bfbebSnyanmisaka typedef struct MppBufLog_t { 49*437bfbebSnyanmisaka RK_U32 group_id; 50*437bfbebSnyanmisaka RK_S32 buffer_id; 51*437bfbebSnyanmisaka MppBufOps ops; 52*437bfbebSnyanmisaka RK_S32 ref_count; 53*437bfbebSnyanmisaka const char *caller; 54*437bfbebSnyanmisaka } MppBufLog; 55*437bfbebSnyanmisaka 56*437bfbebSnyanmisaka typedef struct MppBufLogs_t { 57*437bfbebSnyanmisaka pthread_mutex_t lock; 58*437bfbebSnyanmisaka RK_U16 max_count; 59*437bfbebSnyanmisaka RK_U16 log_count; 60*437bfbebSnyanmisaka RK_U16 log_write; 61*437bfbebSnyanmisaka RK_U16 log_read; 62*437bfbebSnyanmisaka MppBufLog *logs; 63*437bfbebSnyanmisaka } MppBufLogs; 64*437bfbebSnyanmisaka 65*437bfbebSnyanmisaka typedef struct MppBufferImpl_t MppBufferImpl; 66*437bfbebSnyanmisaka typedef struct MppBufferGroupImpl_t MppBufferGroupImpl; 67*437bfbebSnyanmisaka typedef void (*MppBufCallback)(void *, void *); 68*437bfbebSnyanmisaka 69*437bfbebSnyanmisaka // use index instead of pointer to avoid invalid pointer 70*437bfbebSnyanmisaka struct MppBufferImpl_t { 71*437bfbebSnyanmisaka char tag[MPP_TAG_SIZE]; 72*437bfbebSnyanmisaka const char *caller; 73*437bfbebSnyanmisaka pthread_mutex_t lock; 74*437bfbebSnyanmisaka /* parameter store from MppBufferGroup */ 75*437bfbebSnyanmisaka MppAllocator allocator; 76*437bfbebSnyanmisaka MppAllocatorApi *alloc_api; 77*437bfbebSnyanmisaka RK_U32 log_runtime_en; 78*437bfbebSnyanmisaka RK_U32 log_history_en; 79*437bfbebSnyanmisaka RK_U32 group_id; 80*437bfbebSnyanmisaka RK_S32 buffer_id; 81*437bfbebSnyanmisaka MppBufferMode mode; 82*437bfbebSnyanmisaka MppBufferType type; 83*437bfbebSnyanmisaka MppBufLogs *logs; 84*437bfbebSnyanmisaka 85*437bfbebSnyanmisaka MppBufferInfo info; 86*437bfbebSnyanmisaka size_t offset; 87*437bfbebSnyanmisaka size_t length; 88*437bfbebSnyanmisaka 89*437bfbebSnyanmisaka /* cacheable flag */ 90*437bfbebSnyanmisaka RK_U32 uncached; 91*437bfbebSnyanmisaka 92*437bfbebSnyanmisaka /* 93*437bfbebSnyanmisaka * discard: 94*437bfbebSnyanmisaka * used for buf on group reset mode 95*437bfbebSnyanmisaka * set disard value to 1 when frame refcount no zero , 96*437bfbebSnyanmisaka * we will delay relesase buffer after refcount to zero, 97*437bfbebSnyanmisaka * not put this buf to unused list 98*437bfbebSnyanmisaka */ 99*437bfbebSnyanmisaka RK_S32 discard; 100*437bfbebSnyanmisaka // used flag is for used/unused list detection 101*437bfbebSnyanmisaka RK_U32 used; 102*437bfbebSnyanmisaka RK_S32 ref_count; 103*437bfbebSnyanmisaka struct list_head list_status; 104*437bfbebSnyanmisaka 105*437bfbebSnyanmisaka /* 106*437bfbebSnyanmisaka * mpp_device map for attach / detach operation 107*437bfbebSnyanmisaka */ 108*437bfbebSnyanmisaka struct list_head list_maps; 109*437bfbebSnyanmisaka }; 110*437bfbebSnyanmisaka 111*437bfbebSnyanmisaka struct MppBufferGroupImpl_t { 112*437bfbebSnyanmisaka char tag[MPP_TAG_SIZE]; 113*437bfbebSnyanmisaka const char *caller; 114*437bfbebSnyanmisaka /* parameter store for MppBuffer */ 115*437bfbebSnyanmisaka MppAllocator allocator; 116*437bfbebSnyanmisaka MppAllocatorApi *alloc_api; 117*437bfbebSnyanmisaka MppAllocFlagType flags; 118*437bfbebSnyanmisaka RK_U32 log_runtime_en; 119*437bfbebSnyanmisaka RK_U32 log_history_en; 120*437bfbebSnyanmisaka RK_U32 group_id; 121*437bfbebSnyanmisaka MppBufferMode mode; 122*437bfbebSnyanmisaka MppBufferType type; 123*437bfbebSnyanmisaka 124*437bfbebSnyanmisaka /* group status flag */ 125*437bfbebSnyanmisaka // buffer force clear mode flag 126*437bfbebSnyanmisaka RK_U32 clear_on_exit; 127*437bfbebSnyanmisaka RK_U32 dump_on_exit; 128*437bfbebSnyanmisaka // is_misc: 0 - normal group 1 - misc group 129*437bfbebSnyanmisaka RK_U32 is_misc; 130*437bfbebSnyanmisaka // is_orphan: 0 - normal group 1 - orphan group 131*437bfbebSnyanmisaka RK_U32 is_orphan; 132*437bfbebSnyanmisaka RK_U32 is_finalizing; 133*437bfbebSnyanmisaka // used in limit mode only 134*437bfbebSnyanmisaka size_t limit_size; 135*437bfbebSnyanmisaka RK_S32 limit_count; 136*437bfbebSnyanmisaka // status record 137*437bfbebSnyanmisaka size_t limit; 138*437bfbebSnyanmisaka size_t usage; 139*437bfbebSnyanmisaka RK_S32 buffer_id; 140*437bfbebSnyanmisaka RK_S32 buffer_count; 141*437bfbebSnyanmisaka 142*437bfbebSnyanmisaka // thread that will be signal on buffer return 143*437bfbebSnyanmisaka MppBufCallback callback; 144*437bfbebSnyanmisaka void *arg; 145*437bfbebSnyanmisaka 146*437bfbebSnyanmisaka // link to list_status in MppBufferImpl 147*437bfbebSnyanmisaka pthread_mutex_t buf_lock; 148*437bfbebSnyanmisaka struct hlist_node hlist; 149*437bfbebSnyanmisaka struct list_head list_used; 150*437bfbebSnyanmisaka struct list_head list_unused; 151*437bfbebSnyanmisaka RK_S32 count_used; 152*437bfbebSnyanmisaka RK_S32 count_unused; 153*437bfbebSnyanmisaka 154*437bfbebSnyanmisaka // buffer log function 155*437bfbebSnyanmisaka MppBufLogs *logs; 156*437bfbebSnyanmisaka 157*437bfbebSnyanmisaka // link to the other MppBufferGroupImpl 158*437bfbebSnyanmisaka struct list_head list_group; 159*437bfbebSnyanmisaka }; 160*437bfbebSnyanmisaka 161*437bfbebSnyanmisaka #ifdef __cplusplus 162*437bfbebSnyanmisaka extern "C" { 163*437bfbebSnyanmisaka #endif 164*437bfbebSnyanmisaka 165*437bfbebSnyanmisaka extern RK_U32 mpp_buffer_debug; 166*437bfbebSnyanmisaka 167*437bfbebSnyanmisaka /* 168*437bfbebSnyanmisaka * mpp_buffer_create : create a unused buffer with parameter tag/size/data 169*437bfbebSnyanmisaka * if input buffer is NULL then buffer will be register to unused list 170*437bfbebSnyanmisaka * otherwise the buffer will be register to used list and set to paramter buffer 171*437bfbebSnyanmisaka * 172*437bfbebSnyanmisaka * mpp_buffer_mmap : The created mpp_buffer can not be accessed directly. 173*437bfbebSnyanmisaka * It required map to access. This is an optimization 174*437bfbebSnyanmisaka * for reducing virtual memory usage. 175*437bfbebSnyanmisaka * 176*437bfbebSnyanmisaka * mpp_buffer_get_unused : get unused buffer with size. it will first search 177*437bfbebSnyanmisaka * the unused list. if failed it will create on from 178*437bfbebSnyanmisaka * group allocator. 179*437bfbebSnyanmisaka * 180*437bfbebSnyanmisaka * mpp_buffer_ref_inc : increase buffer's reference counter. if it is unused 181*437bfbebSnyanmisaka * then it will be moved to used list. 182*437bfbebSnyanmisaka * 183*437bfbebSnyanmisaka * mpp_buffer_ref_dec : decrease buffer's reference counter. if the reference 184*437bfbebSnyanmisaka * reduce to zero buffer will be moved to unused list. 185*437bfbebSnyanmisaka * 186*437bfbebSnyanmisaka * normal call flow will be like this: 187*437bfbebSnyanmisaka * 188*437bfbebSnyanmisaka * mpp_buffer_create - create a unused buffer 189*437bfbebSnyanmisaka * mpp_buffer_get_unused - get the unused buffer 190*437bfbebSnyanmisaka * mpp_buffer_ref_inc/dec - use the buffer 191*437bfbebSnyanmisaka * mpp_buffer_destory - destroy the buffer 192*437bfbebSnyanmisaka */ 193*437bfbebSnyanmisaka MPP_RET mpp_buffer_create(const char *tag, const char *caller, MppBufferGroupImpl *group, MppBufferInfo *info, MppBufferImpl **buffer); 194*437bfbebSnyanmisaka MPP_RET mpp_buffer_mmap(MppBufferImpl *buffer, const char* caller); 195*437bfbebSnyanmisaka MPP_RET mpp_buffer_ref_inc(MppBufferImpl *buffer, const char* caller); 196*437bfbebSnyanmisaka MPP_RET mpp_buffer_ref_dec(MppBufferImpl *buffer, const char* caller); 197*437bfbebSnyanmisaka MPP_RET mpp_buffer_discard(MppBufferImpl *buffer, const char* caller); 198*437bfbebSnyanmisaka MppBufferImpl *mpp_buffer_get_unused(MppBufferGroupImpl *p, size_t size, const char* caller); 199*437bfbebSnyanmisaka RK_U32 mpp_buffer_to_addr(MppBuffer buffer, size_t offset); 200*437bfbebSnyanmisaka MPP_RET mpp_buffer_attach_dev_f(const char *caller, MppBuffer buffer, MppDev dev); 201*437bfbebSnyanmisaka MPP_RET mpp_buffer_detach_dev_f(const char *caller, MppBuffer buffer, MppDev dev); 202*437bfbebSnyanmisaka RK_U32 mpp_buffer_get_iova_f(const char *caller, MppBuffer buffer, MppDev dev); 203*437bfbebSnyanmisaka 204*437bfbebSnyanmisaka #define mpp_buffer_attach_dev(buf, dev) mpp_buffer_attach_dev_f(__FUNCTION__, buf, dev) 205*437bfbebSnyanmisaka #define mpp_buffer_detach_dev(buf, dev) mpp_buffer_detach_dev_f(__FUNCTION__, buf, dev) 206*437bfbebSnyanmisaka #define mpp_buffer_get_iova(buf, dev) mpp_buffer_get_iova_f(__FUNCTION__, buf, dev) 207*437bfbebSnyanmisaka 208*437bfbebSnyanmisaka MPP_RET mpp_buffer_group_init(MppBufferGroupImpl **group, const char *tag, const char *caller, MppBufferMode mode, MppBufferType type); 209*437bfbebSnyanmisaka MPP_RET mpp_buffer_group_deinit(MppBufferGroupImpl *p); 210*437bfbebSnyanmisaka MPP_RET mpp_buffer_group_reset(MppBufferGroupImpl *p); 211*437bfbebSnyanmisaka MPP_RET mpp_buffer_group_set_callback(MppBufferGroupImpl *p, 212*437bfbebSnyanmisaka MppBufCallback callback, void *arg); 213*437bfbebSnyanmisaka // mpp_buffer_group helper function 214*437bfbebSnyanmisaka void mpp_buffer_group_dump(MppBufferGroupImpl *p, const char *caller); 215*437bfbebSnyanmisaka MppBufferGroupImpl *mpp_buffer_get_misc_group(MppBufferMode mode, MppBufferType type); 216*437bfbebSnyanmisaka 217*437bfbebSnyanmisaka #ifdef __cplusplus 218*437bfbebSnyanmisaka } 219*437bfbebSnyanmisaka #endif 220*437bfbebSnyanmisaka 221*437bfbebSnyanmisaka #endif /*__MPP_BUFFER_IMPL_H__*/ 222