2573 lines
		
	
	
		
			72 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2573 lines
		
	
	
		
			72 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  *
 | |
|  * (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 <linux/anon_inodes.h>
 | |
| #include <linux/atomic.h>
 | |
| #include <linux/file.h>
 | |
| #include <linux/mutex.h>
 | |
| #include <linux/poll.h>
 | |
| #include <linux/spinlock.h>
 | |
| #include <linux/string.h>
 | |
| #include <linux/stringify.h>
 | |
| #include <linux/timer.h>
 | |
| #include <linux/wait.h>
 | |
| 
 | |
| #include <mali_kbase.h>
 | |
| #include <mali_kbase_jm.h>
 | |
| #include <mali_kbase_tlstream.h>
 | |
| 
 | |
| /*****************************************************************************/
 | |
| 
 | |
| /* 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);
 | |
| }
 |