/* * * (C) COPYRIGHT 2015-2017 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software * Foundation, and any use by you of this program is subject to the terms * of such GNU licence. * * A copy of the licence is included with the program, and can also be obtained * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include /*****************************************************************************/ /* The version of swtrace protocol used in timeline stream. */ #define SWTRACE_VERSION 3 /* The maximum expected length of string in tracepoint descriptor. */ #define STRLEN_MAX 64 /* bytes */ /* The number of nanoseconds in a second. */ #define NSECS_IN_SEC 1000000000ull /* ns */ /* The period of autoflush checker execution in milliseconds. */ #define AUTOFLUSH_INTERVAL 1000 /* ms */ /* The maximum size of a single packet used by timeline. */ #define PACKET_SIZE 4096 /* bytes */ /* The number of packets used by one timeline stream. */ #define PACKET_COUNT 16 /* The number of bytes reserved for packet header. * These value must be defined according to MIPE documentation. */ #define PACKET_HEADER_SIZE 8 /* bytes */ /* The number of bytes reserved for packet sequence number. * These value must be defined according to MIPE documentation. */ #define PACKET_NUMBER_SIZE 4 /* bytes */ /* Packet header - first word. * These values must be defined according to MIPE documentation. */ #define PACKET_STREAMID_POS 0 #define PACKET_STREAMID_LEN 8 #define PACKET_RSVD1_POS (PACKET_STREAMID_POS + PACKET_STREAMID_LEN) #define PACKET_RSVD1_LEN 8 #define PACKET_TYPE_POS (PACKET_RSVD1_POS + PACKET_RSVD1_LEN) #define PACKET_TYPE_LEN 3 #define PACKET_CLASS_POS (PACKET_TYPE_POS + PACKET_TYPE_LEN) #define PACKET_CLASS_LEN 7 #define PACKET_FAMILY_POS (PACKET_CLASS_POS + PACKET_CLASS_LEN) #define PACKET_FAMILY_LEN 6 /* Packet header - second word * These values must be defined according to MIPE documentation. */ #define PACKET_LENGTH_POS 0 #define PACKET_LENGTH_LEN 24 #define PACKET_SEQBIT_POS (PACKET_LENGTH_POS + PACKET_LENGTH_LEN) #define PACKET_SEQBIT_LEN 1 #define PACKET_RSVD2_POS (PACKET_SEQBIT_POS + PACKET_SEQBIT_LEN) #define PACKET_RSVD2_LEN 7 /* Types of streams generated by timeline. * Order is significant! Header streams must precede respective body streams. */ enum tl_stream_type { TL_STREAM_TYPE_OBJ_HEADER, TL_STREAM_TYPE_OBJ_SUMMARY, TL_STREAM_TYPE_OBJ, TL_STREAM_TYPE_AUX_HEADER, TL_STREAM_TYPE_AUX, TL_STREAM_TYPE_COUNT }; /* Timeline packet family ids. * Values are significant! Check MIPE documentation. */ enum tl_packet_family { TL_PACKET_FAMILY_CTRL = 0, /* control packets */ TL_PACKET_FAMILY_TL = 1, /* timeline packets */ TL_PACKET_FAMILY_COUNT }; /* Packet classes used in timeline streams. * Values are significant! Check MIPE documentation. */ enum tl_packet_class { TL_PACKET_CLASS_OBJ = 0, /* timeline objects packet */ TL_PACKET_CLASS_AUX = 1, /* auxiliary events packet */ }; /* Packet types used in timeline streams. * Values are significant! Check MIPE documentation. */ enum tl_packet_type { TL_PACKET_TYPE_HEADER = 0, /* stream's header/directory */ TL_PACKET_TYPE_BODY = 1, /* stream's body */ TL_PACKET_TYPE_SUMMARY = 2, /* stream's summary */ }; /* Message ids of trace events that are recorded in the timeline stream. */ enum tl_msg_id_obj { /* Timeline object events. */ KBASE_TL_NEW_CTX, KBASE_TL_NEW_GPU, KBASE_TL_NEW_LPU, KBASE_TL_NEW_ATOM, KBASE_TL_NEW_AS, KBASE_TL_DEL_CTX, KBASE_TL_DEL_ATOM, KBASE_TL_LIFELINK_LPU_GPU, KBASE_TL_LIFELINK_AS_GPU, KBASE_TL_RET_CTX_LPU, KBASE_TL_RET_ATOM_CTX, KBASE_TL_RET_ATOM_LPU, KBASE_TL_NRET_CTX_LPU, KBASE_TL_NRET_ATOM_CTX, KBASE_TL_NRET_ATOM_LPU, KBASE_TL_RET_AS_CTX, KBASE_TL_NRET_AS_CTX, KBASE_TL_RET_ATOM_AS, KBASE_TL_NRET_ATOM_AS, KBASE_TL_DEP_ATOM_ATOM, KBASE_TL_NDEP_ATOM_ATOM, KBASE_TL_RDEP_ATOM_ATOM, KBASE_TL_ATTRIB_ATOM_CONFIG, KBASE_TL_ATTRIB_ATOM_PRIORITY, KBASE_TL_ATTRIB_ATOM_STATE, KBASE_TL_ATTRIB_ATOM_PRIORITY_CHANGE, KBASE_TL_ATTRIB_ATOM_JIT, KBASE_TL_ATTRIB_AS_CONFIG, KBASE_TL_EVENT_LPU_SOFTSTOP, KBASE_TL_EVENT_ATOM_SOFTSTOP_EX, KBASE_TL_EVENT_ATOM_SOFTSTOP_ISSUE, /* Job dump specific events. */ KBASE_JD_GPU_SOFT_RESET }; /* Message ids of trace events that are recorded in the auxiliary stream. */ enum tl_msg_id_aux { KBASE_AUX_PM_STATE, KBASE_AUX_PAGEFAULT, KBASE_AUX_PAGESALLOC, KBASE_AUX_DEVFREQ_TARGET, KBASE_AUX_PROTECTED_ENTER_START, KBASE_AUX_PROTECTED_ENTER_END, KBASE_AUX_PROTECTED_LEAVE_START, KBASE_AUX_PROTECTED_LEAVE_END }; /*****************************************************************************/ /** * struct tl_stream - timeline stream structure * @lock: message order lock * @buffer: array of buffers * @wbi: write buffer index * @rbi: read buffer index * @numbered: if non-zero stream's packets are sequentially numbered * @autoflush_counter: counter tracking stream's autoflush state * * This structure holds information needed to construct proper packets in the * timeline stream. Each message in sequence must bear timestamp that is greater * to one in previous message in the same stream. For this reason lock is held * throughout the process of message creation. Each stream contains set of * buffers. Each buffer will hold one MIPE packet. In case there is no free * space required to store incoming message the oldest buffer is discarded. * Each packet in timeline body stream has sequence number embedded (this value * must increment monotonically and is used by packets receiver to discover * buffer overflows. * Autoflush counter is set to negative number when there is no data pending * for flush and it is set to zero on every update of the buffer. Autoflush * timer will increment the counter by one on every expiry. In case there will * be no activity on the buffer during two consecutive timer expiries, stream * buffer will be flushed. */ struct tl_stream { spinlock_t lock; struct { atomic_t size; /* number of bytes in buffer */ char data[PACKET_SIZE]; /* buffer's data */ } buffer[PACKET_COUNT]; atomic_t wbi; atomic_t rbi; int numbered; atomic_t autoflush_counter; }; /** * struct tp_desc - tracepoint message descriptor structure * @id: tracepoint ID identifying message in stream * @id_str: human readable version of tracepoint ID * @name: tracepoint description * @arg_types: tracepoint's arguments types declaration * @arg_names: comma separated list of tracepoint's arguments names */ struct tp_desc { u32 id; const char *id_str; const char *name; const char *arg_types; const char *arg_names; }; /*****************************************************************************/ /* Configuration of timeline streams generated by kernel. * Kernel emit only streams containing either timeline object events or * auxiliary events. All streams have stream id value of 1 (as opposed to user * space streams that have value of 0). */ static const struct { enum tl_packet_family pkt_family; enum tl_packet_class pkt_class; enum tl_packet_type pkt_type; unsigned int stream_id; } tl_stream_cfg[TL_STREAM_TYPE_COUNT] = { {TL_PACKET_FAMILY_TL, TL_PACKET_CLASS_OBJ, TL_PACKET_TYPE_HEADER, 1}, {TL_PACKET_FAMILY_TL, TL_PACKET_CLASS_OBJ, TL_PACKET_TYPE_SUMMARY, 1}, {TL_PACKET_FAMILY_TL, TL_PACKET_CLASS_OBJ, TL_PACKET_TYPE_BODY, 1}, {TL_PACKET_FAMILY_TL, TL_PACKET_CLASS_AUX, TL_PACKET_TYPE_HEADER, 1}, {TL_PACKET_FAMILY_TL, TL_PACKET_CLASS_AUX, TL_PACKET_TYPE_BODY, 1} }; /* The timeline streams generated by kernel. */ static struct tl_stream *tl_stream[TL_STREAM_TYPE_COUNT]; /* Autoflush timer. */ static struct timer_list autoflush_timer; /* If non-zero autoflush timer is active. */ static atomic_t autoflush_timer_active; /* Reader lock. Only one reader is allowed to have access to the timeline * streams at any given time. */ static DEFINE_MUTEX(tl_reader_lock); /* Timeline stream event queue. */ static DECLARE_WAIT_QUEUE_HEAD(tl_event_queue); /* The timeline stream file operations functions. */ static ssize_t kbasep_tlstream_read( struct file *filp, char __user *buffer, size_t size, loff_t *f_pos); static unsigned int kbasep_tlstream_poll(struct file *filp, poll_table *wait); static int kbasep_tlstream_release(struct inode *inode, struct file *filp); /* The timeline stream file operations structure. */ static const struct file_operations kbasep_tlstream_fops = { .release = kbasep_tlstream_release, .read = kbasep_tlstream_read, .poll = kbasep_tlstream_poll, }; /* Descriptors of timeline messages transmitted in object events stream. */ static const struct tp_desc tp_desc_obj[] = { { KBASE_TL_NEW_CTX, __stringify(KBASE_TL_NEW_CTX), "object ctx is created", "@pII", "ctx,ctx_nr,tgid" }, { KBASE_TL_NEW_GPU, __stringify(KBASE_TL_NEW_GPU), "object gpu is created", "@pII", "gpu,gpu_id,core_count" }, { KBASE_TL_NEW_LPU, __stringify(KBASE_TL_NEW_LPU), "object lpu is created", "@pII", "lpu,lpu_nr,lpu_fn" }, { KBASE_TL_NEW_ATOM, __stringify(KBASE_TL_NEW_ATOM), "object atom is created", "@pI", "atom,atom_nr" }, { KBASE_TL_NEW_AS, __stringify(KBASE_TL_NEW_AS), "address space object is created", "@pI", "address_space,as_nr" }, { KBASE_TL_DEL_CTX, __stringify(KBASE_TL_DEL_CTX), "context is destroyed", "@p", "ctx" }, { KBASE_TL_DEL_ATOM, __stringify(KBASE_TL_DEL_ATOM), "atom is destroyed", "@p", "atom" }, { KBASE_TL_LIFELINK_LPU_GPU, __stringify(KBASE_TL_LIFELINK_LPU_GPU), "lpu is deleted with gpu", "@pp", "lpu,gpu" }, { KBASE_TL_LIFELINK_AS_GPU, __stringify(KBASE_TL_LIFELINK_AS_GPU), "address space is deleted with gpu", "@pp", "address_space,gpu" }, { KBASE_TL_RET_CTX_LPU, __stringify(KBASE_TL_RET_CTX_LPU), "context is retained by lpu", "@pp", "ctx,lpu" }, { KBASE_TL_RET_ATOM_CTX, __stringify(KBASE_TL_RET_ATOM_CTX), "atom is retained by context", "@pp", "atom,ctx" }, { KBASE_TL_RET_ATOM_LPU, __stringify(KBASE_TL_RET_ATOM_LPU), "atom is retained by lpu", "@pps", "atom,lpu,attrib_match_list" }, { KBASE_TL_NRET_CTX_LPU, __stringify(KBASE_TL_NRET_CTX_LPU), "context is released by lpu", "@pp", "ctx,lpu" }, { KBASE_TL_NRET_ATOM_CTX, __stringify(KBASE_TL_NRET_ATOM_CTX), "atom is released by context", "@pp", "atom,ctx" }, { KBASE_TL_NRET_ATOM_LPU, __stringify(KBASE_TL_NRET_ATOM_LPU), "atom is released by lpu", "@pp", "atom,lpu" }, { KBASE_TL_RET_AS_CTX, __stringify(KBASE_TL_RET_AS_CTX), "address space is retained by context", "@pp", "address_space,ctx" }, { KBASE_TL_NRET_AS_CTX, __stringify(KBASE_TL_NRET_AS_CTX), "address space is released by context", "@pp", "address_space,ctx" }, { KBASE_TL_RET_ATOM_AS, __stringify(KBASE_TL_RET_ATOM_AS), "atom is retained by address space", "@pp", "atom,address_space" }, { KBASE_TL_NRET_ATOM_AS, __stringify(KBASE_TL_NRET_ATOM_AS), "atom is released by address space", "@pp", "atom,address_space" }, { KBASE_TL_DEP_ATOM_ATOM, __stringify(KBASE_TL_DEP_ATOM_ATOM), "atom2 depends on atom1", "@pp", "atom1,atom2" }, { KBASE_TL_NDEP_ATOM_ATOM, __stringify(KBASE_TL_NDEP_ATOM_ATOM), "atom2 no longer depends on atom1", "@pp", "atom1,atom2" }, { KBASE_TL_RDEP_ATOM_ATOM, __stringify(KBASE_TL_RDEP_ATOM_ATOM), "resolved dependecy of atom2 depending on atom1", "@pp", "atom1,atom2" }, { KBASE_TL_ATTRIB_ATOM_CONFIG, __stringify(KBASE_TL_ATTRIB_ATOM_CONFIG), "atom job slot attributes", "@pLLI", "atom,descriptor,affinity,config" }, { KBASE_TL_ATTRIB_ATOM_PRIORITY, __stringify(KBASE_TL_ATTRIB_ATOM_PRIORITY), "atom priority", "@pI", "atom,prio" }, { KBASE_TL_ATTRIB_ATOM_STATE, __stringify(KBASE_TL_ATTRIB_ATOM_STATE), "atom state", "@pI", "atom,state" }, { KBASE_TL_ATTRIB_ATOM_PRIORITY_CHANGE, __stringify(KBASE_TL_ATTRIB_ATOM_PRIORITY_CHANGE), "atom caused priority change", "@p", "atom" }, { KBASE_TL_ATTRIB_ATOM_JIT, __stringify(KBASE_TL_ATTRIB_ATOM_JIT), "jit done for atom", "@pLL", "atom,edit_addr,new_addr" }, { KBASE_TL_ATTRIB_AS_CONFIG, __stringify(KBASE_TL_ATTRIB_AS_CONFIG), "address space attributes", "@pLLL", "address_space,transtab,memattr,transcfg" }, { KBASE_TL_EVENT_LPU_SOFTSTOP, __stringify(KBASE_TL_EVENT_LPU_SOFTSTOP), "softstop event on given lpu", "@p", "lpu" }, { KBASE_TL_EVENT_ATOM_SOFTSTOP_EX, __stringify(KBASE_TL_EVENT_ATOM_SOFTSTOP_EX), "atom softstopped", "@p", "atom" }, { KBASE_TL_EVENT_ATOM_SOFTSTOP_ISSUE, __stringify(KBASE_TL_EVENT_SOFTSTOP_ISSUE), "atom softstop issued", "@p", "atom" }, { KBASE_JD_GPU_SOFT_RESET, __stringify(KBASE_JD_GPU_SOFT_RESET), "gpu soft reset", "@p", "gpu" }, }; /* Descriptors of timeline messages transmitted in auxiliary events stream. */ static const struct tp_desc tp_desc_aux[] = { { KBASE_AUX_PM_STATE, __stringify(KBASE_AUX_PM_STATE), "PM state", "@IL", "core_type,core_state_bitset" }, { KBASE_AUX_PAGEFAULT, __stringify(KBASE_AUX_PAGEFAULT), "Page fault", "@IL", "ctx_nr,page_cnt_change" }, { KBASE_AUX_PAGESALLOC, __stringify(KBASE_AUX_PAGESALLOC), "Total alloc pages change", "@IL", "ctx_nr,page_cnt" }, { KBASE_AUX_DEVFREQ_TARGET, __stringify(KBASE_AUX_DEVFREQ_TARGET), "New device frequency target", "@L", "target_freq" }, { KBASE_AUX_PROTECTED_ENTER_START, __stringify(KBASE_AUX_PROTECTED_ENTER_START), "enter protected mode start", "@p", "gpu" }, { KBASE_AUX_PROTECTED_ENTER_END, __stringify(KBASE_AUX_PROTECTED_ENTER_END), "enter protected mode end", "@p", "gpu" }, { KBASE_AUX_PROTECTED_LEAVE_START, __stringify(KBASE_AUX_PROTECTED_LEAVE_START), "leave protected mode start", "@p", "gpu" }, { KBASE_AUX_PROTECTED_LEAVE_END, __stringify(KBASE_AUX_PROTECTED_LEAVE_END), "leave protected mode end", "@p", "gpu" } }; #if MALI_UNIT_TEST /* Number of bytes read by user. */ static atomic_t tlstream_bytes_collected = {0}; /* Number of bytes generated by tracepoint messages. */ static atomic_t tlstream_bytes_generated = {0}; #endif /* MALI_UNIT_TEST */ /*****************************************************************************/ /* Indicator of whether the timeline stream file descriptor is used. */ atomic_t kbase_tlstream_enabled = {0}; /*****************************************************************************/ /** * kbasep_tlstream_get_timestamp - return timestamp * * Function returns timestamp value based on raw monotonic timer. Value will * wrap around zero in case of overflow. * Return: timestamp value */ static u64 kbasep_tlstream_get_timestamp(void) { struct timespec64 ts; u64 timestamp; ktime_get_raw_ts64(&ts); timestamp = (u64)ts.tv_sec * NSECS_IN_SEC + ts.tv_nsec; return timestamp; } /** * kbasep_tlstream_write_bytes - write data to message buffer * @buffer: buffer where data will be written * @pos: position in the buffer where to place data * @bytes: pointer to buffer holding data * @len: length of data to be written * * Return: updated position in the buffer */ static size_t kbasep_tlstream_write_bytes( char *buffer, size_t pos, const void *bytes, size_t len) { KBASE_DEBUG_ASSERT(buffer); KBASE_DEBUG_ASSERT(bytes); memcpy(&buffer[pos], bytes, len); return pos + len; } /** * kbasep_tlstream_write_string - write string to message buffer * @buffer: buffer where data will be written * @pos: position in the buffer where to place data * @string: pointer to buffer holding the source string * @max_write_size: number of bytes that can be stored in buffer * * Return: updated position in the buffer */ static size_t kbasep_tlstream_write_string( char *buffer, size_t pos, const char *string, size_t max_write_size) { u32 string_len; KBASE_DEBUG_ASSERT(buffer); KBASE_DEBUG_ASSERT(string); /* Timeline string consists of at least string length and nul * terminator. */ KBASE_DEBUG_ASSERT(max_write_size >= sizeof(string_len) + sizeof(char)); max_write_size -= sizeof(string_len); string_len = strlcpy( &buffer[pos + sizeof(string_len)], string, max_write_size); string_len += sizeof(char); /* Make sure that the source string fit into the buffer. */ KBASE_DEBUG_ASSERT(string_len <= max_write_size); /* Update string length. */ memcpy(&buffer[pos], &string_len, sizeof(string_len)); return pos + sizeof(string_len) + string_len; } /** * kbasep_tlstream_write_timestamp - write timestamp to message buffer * @buffer: buffer where data will be written * @pos: position in the buffer where to place data * * Return: updated position in the buffer */ static size_t kbasep_tlstream_write_timestamp(void *buffer, size_t pos) { u64 timestamp = kbasep_tlstream_get_timestamp(); return kbasep_tlstream_write_bytes( buffer, pos, ×tamp, sizeof(timestamp)); } /** * kbasep_tlstream_put_bits - put bits in a word * @word: pointer to the words being modified * @value: value that shall be written to given position * @bitpos: position where value shall be written (in bits) * @bitlen: length of value (in bits) */ static void kbasep_tlstream_put_bits( u32 *word, u32 value, unsigned int bitpos, unsigned int bitlen) { const u32 mask = ((1 << bitlen) - 1) << bitpos; KBASE_DEBUG_ASSERT(word); KBASE_DEBUG_ASSERT((0 != bitlen) && (32 >= bitlen)); KBASE_DEBUG_ASSERT((bitpos + bitlen) <= 32); *word &= ~mask; *word |= ((value << bitpos) & mask); } /** * kbasep_tlstream_packet_header_setup - setup the packet header * @buffer: pointer to the buffer * @pkt_family: packet's family * @pkt_type: packet's type * @pkt_class: packet's class * @stream_id: stream id * @numbered: non-zero if this stream is numbered * * Function sets up immutable part of packet header in the given buffer. */ static void kbasep_tlstream_packet_header_setup( char *buffer, enum tl_packet_family pkt_family, enum tl_packet_class pkt_class, enum tl_packet_type pkt_type, unsigned int stream_id, int numbered) { u32 word0 = 0; u32 word1 = 0; KBASE_DEBUG_ASSERT(buffer); KBASE_DEBUG_ASSERT(pkt_family == TL_PACKET_FAMILY_TL); KBASE_DEBUG_ASSERT( (pkt_type == TL_PACKET_TYPE_HEADER) || (pkt_type == TL_PACKET_TYPE_SUMMARY) || (pkt_type == TL_PACKET_TYPE_BODY)); KBASE_DEBUG_ASSERT( (pkt_class == TL_PACKET_CLASS_OBJ) || (pkt_class == TL_PACKET_CLASS_AUX)); kbasep_tlstream_put_bits( &word0, pkt_family, PACKET_FAMILY_POS, PACKET_FAMILY_LEN); kbasep_tlstream_put_bits( &word0, pkt_class, PACKET_CLASS_POS, PACKET_CLASS_LEN); kbasep_tlstream_put_bits( &word0, pkt_type, PACKET_TYPE_POS, PACKET_TYPE_LEN); kbasep_tlstream_put_bits( &word0, stream_id, PACKET_STREAMID_POS, PACKET_STREAMID_LEN); if (numbered) kbasep_tlstream_put_bits( &word1, 1, PACKET_SEQBIT_POS, PACKET_SEQBIT_LEN); memcpy(&buffer[0], &word0, sizeof(word0)); memcpy(&buffer[sizeof(word0)], &word1, sizeof(word1)); } /** * kbasep_tlstream_packet_header_update - update the packet header * @buffer: pointer to the buffer * @data_size: amount of data carried in this packet * * Function updates mutable part of packet header in the given buffer. * Note that value of data_size must not including size of the header. */ static void kbasep_tlstream_packet_header_update( char *buffer, size_t data_size) { u32 word0; u32 word1; KBASE_DEBUG_ASSERT(buffer); CSTD_UNUSED(word0); memcpy(&word1, &buffer[sizeof(word0)], sizeof(word1)); kbasep_tlstream_put_bits( &word1, data_size, PACKET_LENGTH_POS, PACKET_LENGTH_LEN); memcpy(&buffer[sizeof(word0)], &word1, sizeof(word1)); } /** * kbasep_tlstream_packet_number_update - update the packet number * @buffer: pointer to the buffer * @counter: value of packet counter for this packet's stream * * Function updates packet number embedded within the packet placed in the * given buffer. */ static void kbasep_tlstream_packet_number_update(char *buffer, u32 counter) { KBASE_DEBUG_ASSERT(buffer); memcpy(&buffer[PACKET_HEADER_SIZE], &counter, sizeof(counter)); } /** * kbasep_timeline_stream_reset - reset stream * @stream: pointer to the stream structure * * Function discards all pending messages and resets packet counters. */ static void kbasep_timeline_stream_reset(struct tl_stream *stream) { unsigned int i; for (i = 0; i < PACKET_COUNT; i++) { if (stream->numbered) atomic_set( &stream->buffer[i].size, PACKET_HEADER_SIZE + PACKET_NUMBER_SIZE); else atomic_set(&stream->buffer[i].size, PACKET_HEADER_SIZE); } atomic_set(&stream->wbi, 0); atomic_set(&stream->rbi, 0); } /** * kbasep_timeline_stream_init - initialize timeline stream * @stream: pointer to the stream structure * @stream_type: stream type */ static void kbasep_timeline_stream_init( struct tl_stream *stream, enum tl_stream_type stream_type) { unsigned int i; KBASE_DEBUG_ASSERT(stream); KBASE_DEBUG_ASSERT(TL_STREAM_TYPE_COUNT > stream_type); spin_lock_init(&stream->lock); /* All packets carrying tracepoints shall be numbered. */ if (TL_PACKET_TYPE_BODY == tl_stream_cfg[stream_type].pkt_type) stream->numbered = 1; else stream->numbered = 0; for (i = 0; i < PACKET_COUNT; i++) kbasep_tlstream_packet_header_setup( stream->buffer[i].data, tl_stream_cfg[stream_type].pkt_family, tl_stream_cfg[stream_type].pkt_class, tl_stream_cfg[stream_type].pkt_type, tl_stream_cfg[stream_type].stream_id, stream->numbered); kbasep_timeline_stream_reset(tl_stream[stream_type]); } /** * kbasep_timeline_stream_term - terminate timeline stream * @stream: pointer to the stream structure */ static void kbasep_timeline_stream_term(struct tl_stream *stream) { KBASE_DEBUG_ASSERT(stream); } /** * kbasep_tlstream_msgbuf_submit - submit packet to the user space * @stream: pointer to the stream structure * @wb_idx_raw: write buffer index * @wb_size: length of data stored in current buffer * * Function updates currently written buffer with packet header. Then write * index is incremented and buffer is handled to user space. Parameters * of new buffer are returned using provided arguments. * * Return: length of data in new buffer * * Warning: User must update the stream structure with returned value. */ static size_t kbasep_tlstream_msgbuf_submit( struct tl_stream *stream, unsigned int wb_idx_raw, unsigned int wb_size) { unsigned int rb_idx_raw = atomic_read(&stream->rbi); unsigned int wb_idx = wb_idx_raw % PACKET_COUNT; /* Set stream as flushed. */ atomic_set(&stream->autoflush_counter, -1); kbasep_tlstream_packet_header_update( stream->buffer[wb_idx].data, wb_size - PACKET_HEADER_SIZE); if (stream->numbered) kbasep_tlstream_packet_number_update( stream->buffer[wb_idx].data, wb_idx_raw); /* Increasing write buffer index will expose this packet to the reader. * As stream->lock is not taken on reader side we must make sure memory * is updated correctly before this will happen. */ smp_wmb(); wb_idx_raw++; atomic_set(&stream->wbi, wb_idx_raw); /* Inform user that packets are ready for reading. */ wake_up_interruptible(&tl_event_queue); /* Detect and mark overflow in this stream. */ if (PACKET_COUNT == wb_idx_raw - rb_idx_raw) { /* Reader side depends on this increment to correctly handle * overflows. The value shall be updated only if it was not * modified by the reader. The data holding buffer will not be * updated before stream->lock is released, however size of the * buffer will. Make sure this increment is globally visible * before information about selected write buffer size. */ atomic_cmpxchg(&stream->rbi, rb_idx_raw, rb_idx_raw + 1); } wb_size = PACKET_HEADER_SIZE; if (stream->numbered) wb_size += PACKET_NUMBER_SIZE; return wb_size; } /** * kbasep_tlstream_msgbuf_acquire - lock selected stream and reserves buffer * @stream_type: type of the stream that shall be locked * @msg_size: message size * @flags: pointer to store flags passed back on stream release * * Function will lock the stream and reserve the number of bytes requested * in msg_size for the user. * * Return: pointer to the buffer where message can be stored * * Warning: Stream must be released with kbasep_tlstream_msgbuf_release(). * Only atomic operations are allowed while stream is locked * (i.e. do not use any operation that may sleep). */ static char *kbasep_tlstream_msgbuf_acquire( enum tl_stream_type stream_type, size_t msg_size, unsigned long *flags) __acquires(&stream->lock) { struct tl_stream *stream; unsigned int wb_idx_raw; unsigned int wb_idx; size_t wb_size; KBASE_DEBUG_ASSERT(TL_STREAM_TYPE_COUNT > stream_type); KBASE_DEBUG_ASSERT( PACKET_SIZE - PACKET_HEADER_SIZE - PACKET_NUMBER_SIZE >= msg_size); stream = tl_stream[stream_type]; spin_lock_irqsave(&stream->lock, *flags); wb_idx_raw = atomic_read(&stream->wbi); wb_idx = wb_idx_raw % PACKET_COUNT; wb_size = atomic_read(&stream->buffer[wb_idx].size); /* Select next buffer if data will not fit into current one. */ if (PACKET_SIZE < wb_size + msg_size) { wb_size = kbasep_tlstream_msgbuf_submit( stream, wb_idx_raw, wb_size); wb_idx = (wb_idx_raw + 1) % PACKET_COUNT; } /* Reserve space in selected buffer. */ atomic_set(&stream->buffer[wb_idx].size, wb_size + msg_size); #if MALI_UNIT_TEST atomic_add(msg_size, &tlstream_bytes_generated); #endif /* MALI_UNIT_TEST */ return &stream->buffer[wb_idx].data[wb_size]; } /** * kbasep_tlstream_msgbuf_release - unlock selected stream * @stream_type: type of the stream that shall be locked * @flags: value obtained during stream acquire * * Function releases stream that has been previously locked with a call to * kbasep_tlstream_msgbuf_acquire(). */ static void kbasep_tlstream_msgbuf_release( enum tl_stream_type stream_type, unsigned long flags) __releases(&stream->lock) { struct tl_stream *stream; KBASE_DEBUG_ASSERT(TL_STREAM_TYPE_COUNT > stream_type); stream = tl_stream[stream_type]; /* Mark stream as containing unflushed data. */ atomic_set(&stream->autoflush_counter, 0); spin_unlock_irqrestore(&stream->lock, flags); } /*****************************************************************************/ /** * kbasep_tlstream_flush_stream - flush stream * @stype: type of stream to be flushed * * Flush pending data in timeline stream. */ static void kbasep_tlstream_flush_stream(enum tl_stream_type stype) { struct tl_stream *stream = tl_stream[stype]; unsigned long flags; unsigned int wb_idx_raw; unsigned int wb_idx; size_t wb_size; size_t min_size = PACKET_HEADER_SIZE; if (stream->numbered) min_size += PACKET_NUMBER_SIZE; spin_lock_irqsave(&stream->lock, flags); wb_idx_raw = atomic_read(&stream->wbi); wb_idx = wb_idx_raw % PACKET_COUNT; wb_size = atomic_read(&stream->buffer[wb_idx].size); if (wb_size > min_size) { wb_size = kbasep_tlstream_msgbuf_submit( stream, wb_idx_raw, wb_size); wb_idx = (wb_idx_raw + 1) % PACKET_COUNT; atomic_set(&stream->buffer[wb_idx].size, wb_size); } spin_unlock_irqrestore(&stream->lock, flags); } /** * kbasep_tlstream_autoflush_timer_callback - autoflush timer callback * @data: unused * * Timer is executed periodically to check if any of the stream contains * buffer ready to be submitted to user space. */ static void kbasep_tlstream_autoflush_timer_callback(struct timer_list *t) { enum tl_stream_type stype; int rcode; CSTD_UNUSED(t); for (stype = 0; stype < TL_STREAM_TYPE_COUNT; stype++) { struct tl_stream *stream = tl_stream[stype]; unsigned long flags; unsigned int wb_idx_raw; unsigned int wb_idx; size_t wb_size; size_t min_size = PACKET_HEADER_SIZE; int af_cnt = atomic_read(&stream->autoflush_counter); /* Check if stream contain unflushed data. */ if (0 > af_cnt) continue; /* Check if stream should be flushed now. */ if (af_cnt != atomic_cmpxchg( &stream->autoflush_counter, af_cnt, af_cnt + 1)) continue; if (!af_cnt) continue; /* Autoflush this stream. */ if (stream->numbered) min_size += PACKET_NUMBER_SIZE; spin_lock_irqsave(&stream->lock, flags); wb_idx_raw = atomic_read(&stream->wbi); wb_idx = wb_idx_raw % PACKET_COUNT; wb_size = atomic_read(&stream->buffer[wb_idx].size); if (wb_size > min_size) { wb_size = kbasep_tlstream_msgbuf_submit( stream, wb_idx_raw, wb_size); wb_idx = (wb_idx_raw + 1) % PACKET_COUNT; atomic_set(&stream->buffer[wb_idx].size, wb_size); } spin_unlock_irqrestore(&stream->lock, flags); } if (atomic_read(&autoflush_timer_active)) rcode = mod_timer( &autoflush_timer, jiffies + msecs_to_jiffies(AUTOFLUSH_INTERVAL)); CSTD_UNUSED(rcode); } /** * kbasep_tlstream_packet_pending - check timeline streams for pending packets * @stype: pointer to variable where stream type will be placed * @rb_idx_raw: pointer to variable where read buffer index will be placed * * Function checks all streams for pending packets. It will stop as soon as * packet ready to be submitted to user space is detected. Variables under * pointers, passed as the parameters to this function will be updated with * values pointing to right stream and buffer. * * Return: non-zero if any of timeline streams has at last one packet ready */ static int kbasep_tlstream_packet_pending( enum tl_stream_type *stype, unsigned int *rb_idx_raw) { int pending = 0; KBASE_DEBUG_ASSERT(stype); KBASE_DEBUG_ASSERT(rb_idx_raw); for ( *stype = 0; (*stype < TL_STREAM_TYPE_COUNT) && !pending; (*stype)++) { if (NULL != tl_stream[*stype]) { *rb_idx_raw = atomic_read(&tl_stream[*stype]->rbi); /* Read buffer index may be updated by writer in case of * overflow. Read and write buffer indexes must be * loaded in correct order. */ smp_rmb(); if (atomic_read(&tl_stream[*stype]->wbi) != *rb_idx_raw) pending = 1; } } (*stype)--; return pending; } /** * kbasep_tlstream_read - copy data from streams to buffer provided by user * @filp: pointer to file structure (unused) * @buffer: pointer to the buffer provided by user * @size: maximum amount of data that can be stored in the buffer * @f_pos: pointer to file offset (unused) * * Return: number of bytes stored in the buffer */ static ssize_t kbasep_tlstream_read( struct file *filp, char __user *buffer, size_t size, loff_t *f_pos) { ssize_t copy_len = 0; KBASE_DEBUG_ASSERT(filp); KBASE_DEBUG_ASSERT(f_pos); if (!buffer) return -EINVAL; if ((0 > *f_pos) || (PACKET_SIZE > size)) return -EINVAL; mutex_lock(&tl_reader_lock); while (copy_len < size) { enum tl_stream_type stype; unsigned int rb_idx_raw = 0; unsigned int rb_idx; size_t rb_size; /* If we don't have any data yet, wait for packet to be * submitted. If we already read some packets and there is no * packet pending return back to user. */ if (0 < copy_len) { if (!kbasep_tlstream_packet_pending( &stype, &rb_idx_raw)) break; } else { if (wait_event_interruptible( tl_event_queue, kbasep_tlstream_packet_pending( &stype, &rb_idx_raw))) { copy_len = -ERESTARTSYS; break; } } /* Check if this packet fits into the user buffer. * If so copy its content. */ rb_idx = rb_idx_raw % PACKET_COUNT; rb_size = atomic_read(&tl_stream[stype]->buffer[rb_idx].size); if (rb_size > size - copy_len) break; if (copy_to_user( &buffer[copy_len], tl_stream[stype]->buffer[rb_idx].data, rb_size)) { copy_len = -EFAULT; break; } /* If the rbi still points to the packet we just processed * then there was no overflow so we add the copied size to * copy_len and move rbi on to the next packet */ smp_rmb(); if (atomic_read(&tl_stream[stype]->rbi) == rb_idx_raw) { copy_len += rb_size; atomic_inc(&tl_stream[stype]->rbi); #if MALI_UNIT_TEST atomic_add(rb_size, &tlstream_bytes_collected); #endif /* MALI_UNIT_TEST */ } } mutex_unlock(&tl_reader_lock); return copy_len; } /** * kbasep_tlstream_poll - poll timeline stream for packets * @filp: pointer to file structure * @wait: pointer to poll table * Return: POLLIN if data can be read without blocking, otherwise zero */ static unsigned int kbasep_tlstream_poll(struct file *filp, poll_table *wait) { enum tl_stream_type stream_type; unsigned int rb_idx; KBASE_DEBUG_ASSERT(filp); KBASE_DEBUG_ASSERT(wait); poll_wait(filp, &tl_event_queue, wait); if (kbasep_tlstream_packet_pending(&stream_type, &rb_idx)) return POLLIN; return 0; } /** * kbasep_tlstream_release - release timeline stream descriptor * @inode: pointer to inode structure * @filp: pointer to file structure * * Return always return zero */ static int kbasep_tlstream_release(struct inode *inode, struct file *filp) { KBASE_DEBUG_ASSERT(inode); KBASE_DEBUG_ASSERT(filp); CSTD_UNUSED(inode); CSTD_UNUSED(filp); /* Stop autoflush timer before releasing access to streams. */ atomic_set(&autoflush_timer_active, 0); del_timer_sync(&autoflush_timer); atomic_set(&kbase_tlstream_enabled, 0); return 0; } /** * kbasep_tlstream_timeline_header - prepare timeline header stream packet * @stream_type: type of the stream that will carry header data * @tp_desc: pointer to array with tracepoint descriptors * @tp_count: number of descriptors in the given array * * Functions fills in information about tracepoints stored in body stream * associated with this header stream. */ static void kbasep_tlstream_timeline_header( enum tl_stream_type stream_type, const struct tp_desc *tp_desc, u32 tp_count) { const u8 tv = SWTRACE_VERSION; /* protocol version */ const u8 ps = sizeof(void *); /* pointer size */ size_t msg_size = sizeof(tv) + sizeof(ps) + sizeof(tp_count); char *buffer; size_t pos = 0; unsigned long flags; unsigned int i; KBASE_DEBUG_ASSERT(TL_STREAM_TYPE_COUNT > stream_type); KBASE_DEBUG_ASSERT(tp_desc); /* Calculate the size of the timeline message. */ for (i = 0; i < tp_count; i++) { msg_size += sizeof(tp_desc[i].id); msg_size += strnlen(tp_desc[i].id_str, STRLEN_MAX) + sizeof(char) + sizeof(u32); msg_size += strnlen(tp_desc[i].name, STRLEN_MAX) + sizeof(char) + sizeof(u32); msg_size += strnlen(tp_desc[i].arg_types, STRLEN_MAX) + sizeof(char) + sizeof(u32); msg_size += strnlen(tp_desc[i].arg_names, STRLEN_MAX) + sizeof(char) + sizeof(u32); } KBASE_DEBUG_ASSERT(PACKET_SIZE - PACKET_HEADER_SIZE >= msg_size); buffer = kbasep_tlstream_msgbuf_acquire(stream_type, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &tv, sizeof(tv)); pos = kbasep_tlstream_write_bytes(buffer, pos, &ps, sizeof(ps)); pos = kbasep_tlstream_write_bytes( buffer, pos, &tp_count, sizeof(tp_count)); for (i = 0; i < tp_count; i++) { pos = kbasep_tlstream_write_bytes( buffer, pos, &tp_desc[i].id, sizeof(tp_desc[i].id)); pos = kbasep_tlstream_write_string( buffer, pos, tp_desc[i].id_str, msg_size - pos); pos = kbasep_tlstream_write_string( buffer, pos, tp_desc[i].name, msg_size - pos); pos = kbasep_tlstream_write_string( buffer, pos, tp_desc[i].arg_types, msg_size - pos); pos = kbasep_tlstream_write_string( buffer, pos, tp_desc[i].arg_names, msg_size - pos); } KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(stream_type, flags); /* We don't expect any more data to be read in this stream. * As header stream must be read before its associated body stream, * make this packet visible to the user straightaway. */ kbasep_tlstream_flush_stream(stream_type); } /*****************************************************************************/ int kbase_tlstream_init(void) { enum tl_stream_type i; /* Prepare stream structures. */ for (i = 0; i < TL_STREAM_TYPE_COUNT; i++) { tl_stream[i] = kmalloc(sizeof(**tl_stream), GFP_KERNEL); if (!tl_stream[i]) break; kbasep_timeline_stream_init(tl_stream[i], i); } if (TL_STREAM_TYPE_COUNT > i) { for (; i > 0; i--) { kbasep_timeline_stream_term(tl_stream[i - 1]); kfree(tl_stream[i - 1]); } return -ENOMEM; } /* Initialize autoflush timer. */ atomic_set(&autoflush_timer_active, 0); timer_setup(&autoflush_timer, kbasep_tlstream_autoflush_timer_callback, 0); return 0; } void kbase_tlstream_term(void) { enum tl_stream_type i; for (i = 0; i < TL_STREAM_TYPE_COUNT; i++) { kbasep_timeline_stream_term(tl_stream[i]); kfree(tl_stream[i]); } } static void kbase_create_timeline_objects(struct kbase_context *kctx) { struct kbase_device *kbdev = kctx->kbdev; unsigned int lpu_id; unsigned int as_nr; struct kbasep_kctx_list_element *element; /* Create LPU objects. */ for (lpu_id = 0; lpu_id < kbdev->gpu_props.num_job_slots; lpu_id++) { u32 *lpu = &kbdev->gpu_props.props.raw_props.js_features[lpu_id]; KBASE_TLSTREAM_TL_SUMMARY_NEW_LPU(lpu, lpu_id, *lpu); } /* Create Address Space objects. */ for (as_nr = 0; as_nr < kbdev->nr_hw_address_spaces; as_nr++) KBASE_TLSTREAM_TL_SUMMARY_NEW_AS(&kbdev->as[as_nr], as_nr); /* Create GPU object and make it retain all LPUs and address spaces. */ KBASE_TLSTREAM_TL_SUMMARY_NEW_GPU( kbdev, kbdev->gpu_props.props.raw_props.gpu_id, kbdev->gpu_props.num_cores); for (lpu_id = 0; lpu_id < kbdev->gpu_props.num_job_slots; lpu_id++) { void *lpu = &kbdev->gpu_props.props.raw_props.js_features[lpu_id]; KBASE_TLSTREAM_TL_SUMMARY_LIFELINK_LPU_GPU(lpu, kbdev); } for (as_nr = 0; as_nr < kbdev->nr_hw_address_spaces; as_nr++) KBASE_TLSTREAM_TL_SUMMARY_LIFELINK_AS_GPU( &kbdev->as[as_nr], kbdev); /* Create object for each known context. */ mutex_lock(&kbdev->kctx_list_lock); list_for_each_entry(element, &kbdev->kctx_list, link) { KBASE_TLSTREAM_TL_SUMMARY_NEW_CTX( element->kctx, (u32)(element->kctx->id), (u32)(element->kctx->tgid)); } /* Before releasing the lock, reset body stream buffers. * This will prevent context creation message to be directed to both * summary and body stream. */ kbase_tlstream_reset_body_streams(); mutex_unlock(&kbdev->kctx_list_lock); /* Static object are placed into summary packet that needs to be * transmitted first. Flush all streams to make it available to * user space. */ kbase_tlstream_flush_streams(); } int kbase_tlstream_acquire(struct kbase_context *kctx, u32 flags) { int ret; u32 tlstream_enabled = TLSTREAM_ENABLED | flags; if (0 == atomic_cmpxchg(&kbase_tlstream_enabled, 0, tlstream_enabled)) { int rcode; ret = anon_inode_getfd( "[mali_tlstream]", &kbasep_tlstream_fops, kctx, O_RDONLY | O_CLOEXEC); if (ret < 0) { atomic_set(&kbase_tlstream_enabled, 0); return ret; } /* Reset and initialize header streams. */ kbasep_timeline_stream_reset( tl_stream[TL_STREAM_TYPE_OBJ_HEADER]); kbasep_timeline_stream_reset( tl_stream[TL_STREAM_TYPE_OBJ_SUMMARY]); kbasep_timeline_stream_reset( tl_stream[TL_STREAM_TYPE_AUX_HEADER]); kbasep_tlstream_timeline_header( TL_STREAM_TYPE_OBJ_HEADER, tp_desc_obj, ARRAY_SIZE(tp_desc_obj)); kbasep_tlstream_timeline_header( TL_STREAM_TYPE_AUX_HEADER, tp_desc_aux, ARRAY_SIZE(tp_desc_aux)); /* Start autoflush timer. */ atomic_set(&autoflush_timer_active, 1); rcode = mod_timer( &autoflush_timer, jiffies + msecs_to_jiffies(AUTOFLUSH_INTERVAL)); CSTD_UNUSED(rcode); /* If job dumping is enabled, readjust the software event's * timeout as the default value of 3 seconds is often * insufficient. */ if (flags & BASE_TLSTREAM_JOB_DUMPING_ENABLED) { dev_info(kctx->kbdev->dev, "Job dumping is enabled, readjusting the software event's timeout\n"); atomic_set(&kctx->kbdev->js_data.soft_job_timeout_ms, 1800000); } /* Summary stream was cleared during acquire. * Create static timeline objects that will be * read by client. */ kbase_create_timeline_objects(kctx); } else { ret = -EBUSY; } return ret; } void kbase_tlstream_flush_streams(void) { enum tl_stream_type stype; for (stype = 0; stype < TL_STREAM_TYPE_COUNT; stype++) kbasep_tlstream_flush_stream(stype); } void kbase_tlstream_reset_body_streams(void) { kbasep_timeline_stream_reset( tl_stream[TL_STREAM_TYPE_OBJ]); kbasep_timeline_stream_reset( tl_stream[TL_STREAM_TYPE_AUX]); } #if MALI_UNIT_TEST void kbase_tlstream_stats(u32 *bytes_collected, u32 *bytes_generated) { KBASE_DEBUG_ASSERT(bytes_collected); KBASE_DEBUG_ASSERT(bytes_generated); *bytes_collected = atomic_read(&tlstream_bytes_collected); *bytes_generated = atomic_read(&tlstream_bytes_generated); } #endif /* MALI_UNIT_TEST */ /*****************************************************************************/ void __kbase_tlstream_tl_summary_new_ctx(void *context, u32 nr, u32 tgid) { const u32 msg_id = KBASE_TL_NEW_CTX; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(context) + sizeof(nr) + sizeof(tgid); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ_SUMMARY, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &context, sizeof(context)); pos = kbasep_tlstream_write_bytes( buffer, pos, &nr, sizeof(nr)); pos = kbasep_tlstream_write_bytes( buffer, pos, &tgid, sizeof(tgid)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ_SUMMARY, flags); } void __kbase_tlstream_tl_summary_new_gpu(void *gpu, u32 id, u32 core_count) { const u32 msg_id = KBASE_TL_NEW_GPU; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(gpu) + sizeof(id) + sizeof(core_count); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ_SUMMARY, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &gpu, sizeof(gpu)); pos = kbasep_tlstream_write_bytes( buffer, pos, &id, sizeof(id)); pos = kbasep_tlstream_write_bytes( buffer, pos, &core_count, sizeof(core_count)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ_SUMMARY, flags); } void __kbase_tlstream_tl_summary_new_lpu(void *lpu, u32 nr, u32 fn) { const u32 msg_id = KBASE_TL_NEW_LPU; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(lpu) + sizeof(nr) + sizeof(fn); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ_SUMMARY, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &lpu, sizeof(lpu)); pos = kbasep_tlstream_write_bytes( buffer, pos, &nr, sizeof(nr)); pos = kbasep_tlstream_write_bytes( buffer, pos, &fn, sizeof(fn)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ_SUMMARY, flags); } void __kbase_tlstream_tl_summary_lifelink_lpu_gpu(void *lpu, void *gpu) { const u32 msg_id = KBASE_TL_LIFELINK_LPU_GPU; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(lpu) + sizeof(gpu); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ_SUMMARY, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &lpu, sizeof(lpu)); pos = kbasep_tlstream_write_bytes( buffer, pos, &gpu, sizeof(gpu)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ_SUMMARY, flags); } void __kbase_tlstream_tl_summary_new_as(void *as, u32 nr) { const u32 msg_id = KBASE_TL_NEW_AS; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(as) + sizeof(nr); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ_SUMMARY, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &as, sizeof(as)); pos = kbasep_tlstream_write_bytes( buffer, pos, &nr, sizeof(nr)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ_SUMMARY, flags); } void __kbase_tlstream_tl_summary_lifelink_as_gpu(void *as, void *gpu) { const u32 msg_id = KBASE_TL_LIFELINK_AS_GPU; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(as) + sizeof(gpu); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ_SUMMARY, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &as, sizeof(as)); pos = kbasep_tlstream_write_bytes( buffer, pos, &gpu, sizeof(gpu)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ_SUMMARY, flags); } /*****************************************************************************/ void __kbase_tlstream_tl_new_ctx(void *context, u32 nr, u32 tgid) { const u32 msg_id = KBASE_TL_NEW_CTX; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(context) + sizeof(nr) + sizeof(tgid); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &context, sizeof(context)); pos = kbasep_tlstream_write_bytes( buffer, pos, &nr, sizeof(nr)); pos = kbasep_tlstream_write_bytes( buffer, pos, &tgid, sizeof(tgid)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_new_atom(void *atom, u32 nr) { const u32 msg_id = KBASE_TL_NEW_ATOM; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(nr); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom, sizeof(atom)); pos = kbasep_tlstream_write_bytes( buffer, pos, &nr, sizeof(nr)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_del_ctx(void *context) { const u32 msg_id = KBASE_TL_DEL_CTX; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(context); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &context, sizeof(context)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_del_atom(void *atom) { const u32 msg_id = KBASE_TL_DEL_ATOM; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom, sizeof(atom)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_ret_ctx_lpu(void *context, void *lpu) { const u32 msg_id = KBASE_TL_RET_CTX_LPU; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(context) + sizeof(lpu); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &context, sizeof(context)); pos = kbasep_tlstream_write_bytes( buffer, pos, &lpu, sizeof(lpu)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_ret_atom_ctx(void *atom, void *context) { const u32 msg_id = KBASE_TL_RET_ATOM_CTX; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(context); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom, sizeof(atom)); pos = kbasep_tlstream_write_bytes( buffer, pos, &context, sizeof(context)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_ret_atom_lpu( void *atom, void *lpu, const char *attrib_match_list) { const u32 msg_id = KBASE_TL_RET_ATOM_LPU; const size_t msg_s0 = sizeof(u32) + sizeof(char) + strnlen(attrib_match_list, STRLEN_MAX); const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(lpu) + msg_s0; unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom, sizeof(atom)); pos = kbasep_tlstream_write_bytes( buffer, pos, &lpu, sizeof(lpu)); pos = kbasep_tlstream_write_string( buffer, pos, attrib_match_list, msg_s0); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_nret_ctx_lpu(void *context, void *lpu) { const u32 msg_id = KBASE_TL_NRET_CTX_LPU; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(context) + sizeof(lpu); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &context, sizeof(context)); pos = kbasep_tlstream_write_bytes( buffer, pos, &lpu, sizeof(lpu)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_nret_atom_ctx(void *atom, void *context) { const u32 msg_id = KBASE_TL_NRET_ATOM_CTX; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(context); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom, sizeof(atom)); pos = kbasep_tlstream_write_bytes( buffer, pos, &context, sizeof(context)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_dep_atom_atom(void *atom1, void *atom2) { const u32 msg_id = KBASE_TL_DEP_ATOM_ATOM; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom1) + sizeof(atom2); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom1, sizeof(atom1)); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom2, sizeof(atom2)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_ndep_atom_atom(void *atom1, void *atom2) { const u32 msg_id = KBASE_TL_NDEP_ATOM_ATOM; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom1) + sizeof(atom2); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom1, sizeof(atom1)); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom2, sizeof(atom2)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_rdep_atom_atom(void *atom1, void *atom2) { const u32 msg_id = KBASE_TL_RDEP_ATOM_ATOM; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom1) + sizeof(atom2); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom1, sizeof(atom1)); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom2, sizeof(atom2)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_nret_atom_lpu(void *atom, void *lpu) { const u32 msg_id = KBASE_TL_NRET_ATOM_LPU; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(lpu); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom, sizeof(atom)); pos = kbasep_tlstream_write_bytes( buffer, pos, &lpu, sizeof(lpu)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_ret_as_ctx(void *as, void *ctx) { const u32 msg_id = KBASE_TL_RET_AS_CTX; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(as) + sizeof(ctx); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &as, sizeof(as)); pos = kbasep_tlstream_write_bytes( buffer, pos, &ctx, sizeof(ctx)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_nret_as_ctx(void *as, void *ctx) { const u32 msg_id = KBASE_TL_NRET_AS_CTX; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(as) + sizeof(ctx); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &as, sizeof(as)); pos = kbasep_tlstream_write_bytes( buffer, pos, &ctx, sizeof(ctx)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_ret_atom_as(void *atom, void *as) { const u32 msg_id = KBASE_TL_RET_ATOM_AS; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(as); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom, sizeof(atom)); pos = kbasep_tlstream_write_bytes( buffer, pos, &as, sizeof(as)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_nret_atom_as(void *atom, void *as) { const u32 msg_id = KBASE_TL_NRET_ATOM_AS; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(as); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom, sizeof(atom)); pos = kbasep_tlstream_write_bytes( buffer, pos, &as, sizeof(as)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_attrib_atom_config( void *atom, u64 jd, u64 affinity, u32 config) { const u32 msg_id = KBASE_TL_ATTRIB_ATOM_CONFIG; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(jd) + sizeof(affinity) + sizeof(config); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom, sizeof(atom)); pos = kbasep_tlstream_write_bytes( buffer, pos, &jd, sizeof(jd)); pos = kbasep_tlstream_write_bytes( buffer, pos, &affinity, sizeof(affinity)); pos = kbasep_tlstream_write_bytes( buffer, pos, &config, sizeof(config)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_attrib_atom_priority(void *atom, u32 prio) { const u32 msg_id = KBASE_TL_ATTRIB_ATOM_PRIORITY; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(prio); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom, sizeof(atom)); pos = kbasep_tlstream_write_bytes( buffer, pos, &prio, sizeof(prio)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_attrib_atom_state(void *atom, u32 state) { const u32 msg_id = KBASE_TL_ATTRIB_ATOM_STATE; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(state); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom, sizeof(atom)); pos = kbasep_tlstream_write_bytes( buffer, pos, &state, sizeof(state)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_attrib_atom_priority_change(void *atom) { const u32 msg_id = KBASE_TL_ATTRIB_ATOM_PRIORITY_CHANGE; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom, sizeof(atom)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_attrib_atom_jit( void *atom, u64 edit_addr, u64 new_addr) { const u32 msg_id = KBASE_TL_ATTRIB_ATOM_JIT; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom) + sizeof(edit_addr) + sizeof(new_addr); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom, sizeof(atom)); pos = kbasep_tlstream_write_bytes( buffer, pos, &edit_addr, sizeof(edit_addr)); pos = kbasep_tlstream_write_bytes( buffer, pos, &new_addr, sizeof(new_addr)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_attrib_as_config( void *as, u64 transtab, u64 memattr, u64 transcfg) { const u32 msg_id = KBASE_TL_ATTRIB_AS_CONFIG; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(as) + sizeof(transtab) + sizeof(memattr) + sizeof(transcfg); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &as, sizeof(as)); pos = kbasep_tlstream_write_bytes( buffer, pos, &transtab, sizeof(transtab)); pos = kbasep_tlstream_write_bytes( buffer, pos, &memattr, sizeof(memattr)); pos = kbasep_tlstream_write_bytes( buffer, pos, &transcfg, sizeof(transcfg)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_event_lpu_softstop(void *lpu) { const u32 msg_id = KBASE_TL_EVENT_LPU_SOFTSTOP; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(lpu); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &lpu, sizeof(lpu)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_event_atom_softstop_ex(void *atom) { const u32 msg_id = KBASE_TL_EVENT_ATOM_SOFTSTOP_EX; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom, sizeof(atom)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_tl_event_atom_softstop_issue(void *atom) { const u32 msg_id = KBASE_TL_EVENT_ATOM_SOFTSTOP_ISSUE; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(atom); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &atom, sizeof(atom)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } void __kbase_tlstream_jd_gpu_soft_reset(void *gpu) { const u32 msg_id = KBASE_JD_GPU_SOFT_RESET; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(gpu); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_OBJ, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &gpu, sizeof(gpu)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_OBJ, flags); } /*****************************************************************************/ void __kbase_tlstream_aux_pm_state(u32 core_type, u64 state) { const u32 msg_id = KBASE_AUX_PM_STATE; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(core_type) + sizeof(state); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_AUX, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &core_type, sizeof(core_type)); pos = kbasep_tlstream_write_bytes(buffer, pos, &state, sizeof(state)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags); } void __kbase_tlstream_aux_pagefault(u32 ctx_nr, u64 page_count_change) { const u32 msg_id = KBASE_AUX_PAGEFAULT; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(ctx_nr) + sizeof(page_count_change); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_AUX, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes(buffer, pos, &ctx_nr, sizeof(ctx_nr)); pos = kbasep_tlstream_write_bytes( buffer, pos, &page_count_change, sizeof(page_count_change)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags); } void __kbase_tlstream_aux_pagesalloc(u32 ctx_nr, u64 page_count) { const u32 msg_id = KBASE_AUX_PAGESALLOC; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(ctx_nr) + sizeof(page_count); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_AUX, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes(buffer, pos, &ctx_nr, sizeof(ctx_nr)); pos = kbasep_tlstream_write_bytes( buffer, pos, &page_count, sizeof(page_count)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags); } void __kbase_tlstream_aux_devfreq_target(u64 target_freq) { const u32 msg_id = KBASE_AUX_DEVFREQ_TARGET; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(target_freq); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_AUX, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &target_freq, sizeof(target_freq)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags); } void __kbase_tlstream_aux_protected_enter_start(void *gpu) { const u32 msg_id = KBASE_AUX_PROTECTED_ENTER_START; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(gpu); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_AUX, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &gpu, sizeof(gpu)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags); } void __kbase_tlstream_aux_protected_enter_end(void *gpu) { const u32 msg_id = KBASE_AUX_PROTECTED_ENTER_END; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(gpu); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_AUX, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &gpu, sizeof(gpu)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags); } void __kbase_tlstream_aux_protected_leave_start(void *gpu) { const u32 msg_id = KBASE_AUX_PROTECTED_LEAVE_START; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(gpu); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_AUX, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &gpu, sizeof(gpu)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags); } void __kbase_tlstream_aux_protected_leave_end(void *gpu) { const u32 msg_id = KBASE_AUX_PROTECTED_LEAVE_END; const size_t msg_size = sizeof(msg_id) + sizeof(u64) + sizeof(gpu); unsigned long flags; char *buffer; size_t pos = 0; buffer = kbasep_tlstream_msgbuf_acquire( TL_STREAM_TYPE_AUX, msg_size, &flags); KBASE_DEBUG_ASSERT(buffer); pos = kbasep_tlstream_write_bytes(buffer, pos, &msg_id, sizeof(msg_id)); pos = kbasep_tlstream_write_timestamp(buffer, pos); pos = kbasep_tlstream_write_bytes( buffer, pos, &gpu, sizeof(gpu)); KBASE_DEBUG_ASSERT(msg_size == pos); kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags); }