123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220 |
- /*
- *
- * (C) COPYRIGHT 2015-2016 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>
- #include <backend/gpu/mali_kbase_device_internal.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_AS_CONFIG,
- /* 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_ISSUE_JOB_SOFTSTOP,
- KBASE_AUX_JOB_SOFTSTOP,
- KBASE_AUX_JOB_SOFTSTOP_EX,
- KBASE_AUX_PAGEFAULT,
- KBASE_AUX_PAGESALLOC
- };
- /*****************************************************************************/
- /**
- * 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_AS_CONFIG,
- __stringify(KBASE_TL_ATTRIB_AS_CONFIG),
- "address space attributes",
- "@pLLL",
- "address_space,transtab,memattr,transcfg"
- },
- {
- 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_ISSUE_JOB_SOFTSTOP,
- __stringify(KBASE_AUX_ISSUE_JOB_SOFTSTOP),
- "Issuing job soft stop",
- "@p",
- "atom"
- },
- {
- KBASE_AUX_JOB_SOFTSTOP,
- __stringify(KBASE_AUX_JOB_SOFTSTOP),
- "Job soft stop",
- "@I",
- "tag_id"
- },
- {
- KBASE_AUX_JOB_SOFTSTOP_EX,
- __stringify(KBASE_AUX_JOB_SOFTSTOP_EX),
- "Job soft stop, more details",
- "@pI",
- "atom,job_type"
- },
- {
- 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"
- }
- };
- /*****************************************************************************/
- /* 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 timespec ts;
- u64 timestamp;
- getrawmonotonic(&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) && (bitlen <= 32));
- 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(stream_type < TL_STREAM_TYPE_COUNT);
- spin_lock_init(&stream->lock);
- /* All packets carrying tracepoints shall be numbered. */
- if (tl_stream_cfg[stream_type].pkt_type == TL_PACKET_TYPE_BODY)
- 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(stream_type < TL_STREAM_TYPE_COUNT);
- 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);
- 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(stream_type < TL_STREAM_TYPE_COUNT);
- 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(unsigned long data)
- {
- enum tl_stream_type stype;
- int rcode;
- CSTD_UNUSED(data);
- 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 (af_cnt < 0)
- 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 (tl_stream[*stype] != NULL) {
- *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(buffer);
- KBASE_DEBUG_ASSERT(f_pos);
- CSTD_UNUSED(filp);
- if ((0 > *f_pos) || (size < PACKET_SIZE))
- return -EINVAL;
- mutex_lock(&tl_reader_lock);
- while (copy_len < size) {
- enum tl_stream_type stype;
- unsigned int rb_idx_raw;
- 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 (copy_len > 0) {
- 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);
- }
- }
- 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(stream_type < TL_STREAM_TYPE_COUNT);
- 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 (i < TL_STREAM_TYPE_COUNT) {
- 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);
- setup_timer(&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]);
- }
- }
- int kbase_tlstream_acquire(struct kbase_context *kctx, int *fd)
- {
- if (atomic_cmpxchg(&kbase_tlstream_enabled, 0, 1) == 0) {
- int rcode;
- *fd = anon_inode_getfd(
- "[mali_tlstream]",
- &kbasep_tlstream_fops,
- kctx,
- O_RDONLY | O_CLOEXEC);
- if (*fd < 0) {
- atomic_set(&kbase_tlstream_enabled, 0);
- return *fd;
- }
- /* 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);
- } else {
- *fd = -EBUSY;
- }
- return 0;
- }
- 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]);
- }
- /*****************************************************************************/
- 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_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_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_issue_job_softstop(void *katom)
- {
- const u32 msg_id = KBASE_AUX_ISSUE_JOB_SOFTSTOP;
- const size_t msg_size =
- sizeof(msg_id) + sizeof(u64) + sizeof(katom);
- 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, &katom, sizeof(katom));
- KBASE_DEBUG_ASSERT(msg_size == pos);
- kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags);
- }
- void __kbase_tlstream_aux_job_softstop(u32 js_id)
- {
- const u32 msg_id = KBASE_AUX_JOB_SOFTSTOP;
- const size_t msg_size =
- sizeof(msg_id) + sizeof(u64) + sizeof(js_id);
- 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, &js_id, sizeof(js_id));
- KBASE_DEBUG_ASSERT(msg_size == pos);
- kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags);
- }
- /**
- * __kbase_tlstream_aux_job_softstop_ex_record - record the trace point
- * @katom: the atom that has been soft-stopped
- * @job_type: the job type
- */
- static void __kbase_tlstream_aux_job_softstop_ex_record(
- void *katom, u32 job_type)
- {
- const u32 msg_id = KBASE_AUX_JOB_SOFTSTOP_EX;
- const size_t msg_size =
- sizeof(msg_id) + sizeof(u64) + sizeof(katom) + sizeof(job_type);
- 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, &katom, sizeof(katom));
- pos = kbasep_tlstream_write_bytes(
- buffer, pos, &job_type, sizeof(job_type));
- KBASE_DEBUG_ASSERT(msg_size == pos);
- kbasep_tlstream_msgbuf_release(TL_STREAM_TYPE_AUX, flags);
- }
- void __kbase_tlstream_aux_job_softstop_ex(struct kbase_jd_atom *katom)
- {
- struct kbase_context *kctx = katom->kctx;
- u64 jd = katom->jc;
- while (jd != 0) {
- struct job_descriptor_header *job;
- struct kbase_vmap_struct map;
- job = kbase_vmap(kctx, jd, sizeof(*job), &map);
- if (!job) {
- dev_err(kctx->kbdev->dev,
- "__kbase_tlstream_aux_job_softstop_ex: failed to map job descriptor 0x%llx for atom 0x%p\n",
- jd, (void *)katom);
- break;
- }
- if (job->exception_status != BASE_JD_EVENT_STOPPED) {
- kbase_vunmap(kctx, &map);
- break;
- }
- __kbase_tlstream_aux_job_softstop_ex_record(
- katom, job->job_type);
- jd = job->job_descriptor_size ?
- job->next_job._64 : job->next_job._32;
- kbase_vunmap(kctx, &map);
- }
- }
- 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);
- }
|