summaryrefslogtreecommitdiff
path: root/Documentation/arm/msm/glink.txt
blob: 814c1180424217664cd5e7ee063e70ceeacdf361 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
Introduction
============

G-Link, short for Generic Link, is a generic link-layer transport that supports
a plug-in framework for physical transports. This allows it to adapt to
different physical transports such as shared memory, UARTs, buses, and DMA.

It is designed to enable zero copy, is power aware, and supports version and
feature negotiation to enable phased upgrades. The design is symmetrical with
the same high-level design and the same client API across all subsystems
regardless of OS.

Hardware description
====================

The hardware is managed by the transport plug-in. In the initial
driver version, this is done by the SMEM Native Transport which requires
shared memory and an interrupt in each direction between the local and remote
subsystems. This transport is a replacement for SMD.

Software description
=================================

G-Link consists of:
 * Client API
 * Core that implements the high-level protocol
 * Transport plug-ins that handle translation of the high-level protocol to wire
   format

The below diagram shows the organization of G-Link. Clients use G-Link to
interface with the Transport Plug-in, which interfaces directly with the
physical transport. The G-Link component is shown in further detail in the
"Design" section.

        +-----------+     +---------+      +-----------+
        |  G-Link   |---->|Transport|----->| Physical  |
        |           |<----| Plug-in |<-----| Transport |
        +-----------+     +---------+      +-----------+

Design
======

G-Link is conceptually broken down into a command and data queue. The command
queue is used to pass commands for synchronizing buffer status, channel state,
and for the equivalent of packet headers. The data queue is reserved for raw
client data.

For every packet in the data queue, there is at least one command
that acts as the packet header that goes through the command queue. This
separation is necessary to support the zero-copy use case for data packets and
for DMA-type transports that need to have the transfer size known ahead of time.

For copy-based transports, the command and data transports can be merged
together in the transport plug-in resulting in traditional packet headers like
we have today in other common protocols such as IP.

As shown in the diagram below, the client itself communicates directly with the
G-Link core, and uses the Transport Interface and the G-Link Core interface to
create the transport plug-in.

                                             +-----------+
                     +------+    +---------+ |           |
                     |      |<---|Transport|-|           |
        +-------+    |      |    |   IF    | |           |
        |Clients|<-->|      |    +---------+ | Transport |
        +-------+    |G-Link|                |  Plug-in  |
                     | Core |                |           |
                     |      | +-------+      |           |
                     |      |-|G-Link |----->|           |
                     |      | |Core IF|      |           |
                     +------+ +-------+      |           |
                                             +-----------+

A channel is a discrete data pipe used by a client to communicate with a
remote system. All channels are multiplexed onto one or more physical
transports.

A receive intent is queued by a client to indicate that it is ready to receive
a packet up to the specified size. The intent is sent to the remote side to
let clients know that they can transmit and expect the client to be able to
process it.

Intents provide back-pressure to transmitting clients and remove the
requirement for flow control. In addition, the intent size is used for
copy-based transports to either reserve buffer space or allocate buffers to
receive data to prevent blocking the underlying transport. Multiple intents
can be queued.

Transport Plug-in
-----------------
The transport plug-in is responsible for marshaling data and commands between
the G-Link core and the physical transport. If the remote side is not running
G-Link, then the transport plug-in will be more complex and will handle
translating G-Link core commands and data into the proper protocol to
interact with the remote system.

Client API
----------
The API into the G-Link core is asynchronous by default, but may have blocking
variants. If necessary, a thin client layer can be built on top of the
asynchronous API to create a synchronous API for clients. All client
notifications are serialized to ensure in-order notification of events.

The G-Link client API includes the following functions for the following
operations. Details of each function are described later in this section.
 * glink_open() - Open a G-Link channel
 * glink_close() - Close a G-Link channel
 * glink_tx() - Transmit data
 * glink_txv() - Transmit a buffer chain
 * glink_queue_rx_intent() - Queue a receive intent
 * glink_rx_done() - Signal consumption of the receive buffer
 * glink_sigs_set() - Set a 32-bit signal field for client-specific signaling.
                      Standard TIOCM bits are reserved in the upper bits of the
                      field as a conviencence for users, but they are 100
                      percent pass-through.
 * glink_sigs_local_get() - Get the local 32-bit control signal field
 * glink_sigs_remote_get() - Get the remote 32-bit control signal field

The TIOCM bitmasks are defined as follows:
   #define SMD_CTR_SIG_SHFT 31
   #define SMD_CTS_SIG_SHFT 30
   #define SMD_CD_SIG_SHFT 29
   #define SMD_RI_SIG_SHFT 28

When a channel is opened by a client, the client provides an open
configuration to the G-Link core as a parameter to the glink_open() function.
This open configuration contains the following information:
 * The name of the transport (optional)
 * The name of the edge (remote processor)
 * The name of the channel

The open configuration also contains function pointers for the following
operations, which are defined by the client:
 * notify_rx() - Notify the client that data has been received
 * notify_rxv() - Notify the client that vector data has been received
 * notify_tx_done() - Notify the client that data has been transmitted
 * notify_state() - Notify the client that the channel's state has changed
 * notify_rx_intent_req() - Notify the client whether their request for a
                            receive intent was granted
 * notify_rx_sigs() - Notify the client that there has been a change in the
                      state of the remote side's control signals
 * notify_rx_abort() - During channel close, return structures associated
                       with receive intents to the client
 * notify_tx_abort() - During channel close, return structures associated
                       with TX packets to the client
 * notify_rx_tracer_pkt() - Notify the client that a tracer packet has been
                            received

Buffer ownership is transferred between the local G-Link and the remote G-Link
using message passing. A typical transmit sequence is as follows:

 1. The remote side queues an RX intent. When the remote client queues the
    intent by calling glink_queue_rx_intent(), the ownership of the buffer
    transfers to the remote G-Link core, which notifies the local G-Link core
    of the receive intent. The remote G-Link core is now ready to receive data
    from the local client. In the zero-copy case, the remote G-Link core does
    not need to allocate a buffer.

        +------+                    +------+                 +------+
        |Local |                    |Remote|                 |Remote|
        |G-Link|                    |G-Link|                 |Client|
        +------+                    +------+                 +------+
           |                           |                        |
           |                           | glink_queue_rx_intent()|
           |                          +-+<---------------------+-+
           |                          |-|                      |-|
           |                          |-|(allocate/reserve     |-|
           |                          |-| buffer)              |-|
           |                          |-|-----+                |-|
           |                          |-|     |                |-|
           |                          |-|<----+                |-|
           |                          +-+                      +-+
           |   send_intent()           |                        |
           |<--------------------------+                        |
           |                           |                        |
           |   (signal)                |                        |
          +-+<-------------------------|                        |
          |-|                          |                        |
          |-|                          |                        |
          |-|                          |                        |
          +-+                          |                        |
           |                           |                        |
        +------+                    +------+                 +------+
        |Local |                    |Remote|                 |Remote|
        |G-Link|                    |G-Link|                 |Client|
        +------+                    +------+                 +------+

 2. The local client can allocate a buffer, fill it, and send it to the remote
    side. If multiple receive intents are available, then a first-fit
    algorithm is used to select the receive intent.

        +------+               +------+      +------+        +------+
        |Local |               |Local |      |Remote|        |Remote|
        |Client|               |G-Link|      |G-Link|        |Client|
        +------+               +------+      +------+        +------+
           |                      |             |               |
           | (Allocate tx buffer) |             |               |
          +-+--------+            |             |               |
          |-|        |            |             |               |
          |-|<-------+            |             |               |
          |-|                     |             |               |
          |-| (Copy data into     |             |               |
          |-|  tx buffer)         |             |               |
          |-|--------+            |             |               |
          |-|        |            |             |               |
          |-|<-------+            |             |               |
          |-|                     |             |               |
          |-| glink_tx()          |             |               |
          |-|------------------->+-+ tx()       |               |
          |-|                    |-|---------->+-+ notify_rx()  |
          |-|                    |-|           |-|------------>+-+
          +-+                    |-| (signal)  |-|             |-|
           |                     |-|---------->|-|             |-|
           |                     +-+           |-|             |-|
           |                      |            +-+             |-|
           |                      |             |              +-+
           |                      |             |               |
        +------+               +------+      +------+        +------+
        |Local |               |Local |      |Remote|        |Remote|
        |Client|               |G-Link|      |G-Link|        |Client|
        +------+               +------+      +------+        +------+

 3. The transmit buffer ownership is returned to the local client after the
    remote client has finished with it. At this point, the local client can
    destroy/reuse the buffer.

        +------+           +------+      +------+            +------+
        |Local |           |Local |      |Remote|            |Remote|
        |Client|           |G-Link|      |G-Link|            |Client|
        +------+           +------+      +------+            +------+
           |                  |             |                   |
           |                  |             |   glink_rx_done() |
           |                  |            +-+<----------------+-+
           |                  |            |-|                 |-|
           |                  |            |-| (copy-based     |-|
           |                  |            |-|  transport:     |-|
           |                  |            |-|  destroy/reuse  |-|
           |                  |            |-|  buffer)        |-|
           |                  |            |-|----------+      +-+
           |                  |            |-|          |       |
           |                  |            |-|          |       |
           |                  |            |-|<---------+       |
           |                  |   tx_done()|-|                  |
           |                 +-+<----------|-|                  |
           |                 |-|           |-|                  |
           |                 |-| (signal)  |-|                  |
           | notify_tx_done()|-|<----------|-|                  |
          +-+<---------------|-|           |-|                  |
          |-|                |-|           +-+                  |
          |-|                |-|            |                   |
          |-|                +-+            |                   |
          +-+                 |             |                   |
           |                  |             |                   |
        +------+           +------+      +------+            +------+
        |Local |           |Local |      |Remote|            |Remote|
        |Client|           |G-Link|      |G-Link|            |Client|
        +------+           +------+      +------+            +------+

Transport Interface
-------------------
The transport interface is used for function calls from the G-Link core to a
G-Link transport. Modules which implement this interface are G-Link
transports. All function calls include the pointer to the transport instance
and the data fields that should be encoded into a command packet to be sent to
the remote processor. These functions act on the transport itself - they
translate the commands into actions for each different transport. This interface
contains APIs for transport negotiation, channel state, channel data, and
power. Requests that change state always have an ACK to synchronize
the state between the local and remote subsystems.

The transport interface is implemented as follows:

struct glink_transport_if {
        /* Negotiation */
        void (*tx_cmd_version)(struct glink_transport_if *if_ptr,
                        uint32_t version,
                        uint32_t features);
        void (*tx_cmd_version_ack)(struct glink_transport_if *if_ptr,
                        uint32_t version,
                        uint32_t features);
        void (*set_version)(struct glink_transport_if *if_ptr, uint32_t version,
                        uint32_t features);

        /* channel state */
        int (*tx_cmd_ch_open)(struct glink_transport_if *if_ptr, uint32_t lcid,
                        const char *name);
        int (*tx_cmd_ch_close)(struct glink_transport_if *if_ptr,
                        uint32_t lcid);
        void (*tx_cmd_ch_remote_open_ack)(struct glink_transport_if *if_ptr,
                        uint32_t rcid);
        void (*tx_cmd_ch_remote_close_ack)(struct glink_transport_if *if_ptr,
                        uint32_t rcid);
        int (*ssr)(struct glink_transport_if *if_ptr);

        /* channel data */
        int (*allocate_rx_intent)(size_t size,
                                  struct glink_core_rx_intent *intent);
        int (*deallocate_rx_intent)(struct glink_core_rx_intent *intent);

        int (*tx_cmd_local_rx_intent)(struct glink_transport_if *if_ptr,
                        uint32_t lcid, size_t size, uint32_t liid);
        void (*tx_cmd_local_rx_done)(struct glink_transport_if *if_ptr,
                        uint32_t lcid, uint32_t liid);
        int (*tx)(struct glink_transport_if *if_ptr, uint32_t lcid,
                        struct glink_core_tx_pkt *pctx);
        int (*tx_cmd_rx_intent_req)(struct glink_transport_if *if_ptr,
                        uint32_t lcid, size_t size);
        int (*tx_cmd_remote_rx_intent_req_ack)(
                        struct glink_transport_if *if_ptr,
                        uint32_t lcid, bool granted);
        int (*tx_cmd_set_sigs)(struct glink_transport_if *if_ptr,
                        uint32_t lcid, uint32_t sigs);

        /* Optional.  If NULL at xprt registration, dummies will be used */
        int (*poll)(struct glink_transport_if *if_ptr, uint32_t lcid);
        int (*mask_rx_irq)(struct glink_transport_if *if_ptr, uint32_t lcid,
                        bool mask, void *pstruct);
        int (*wait_link_down)(struct glink_transport_if *if_ptr);
        int (*tx_cmd_tracer_pkt)(struct glink_transport_if *if_ptr,
                        uint32_t lcid, struct glink_core_tx_pkt *pctx);

        /* private pointer for core */
        struct glink_core_xprt_ctx *glink_core_priv;

        /* core pointer (set during transport registration) */
        struct glink_core_if *glink_core_if_ptr;
};

G-Link Core Interface
---------------------
The G-Link Core Interface is used by the transport to call back into G-Link
core for messages or events received from the transport. This interface has
APIs for transport negotiation, power, channel state, and channel data.
Like the transport interface, requests that change state always have an ACK
to synchronize the state between the local and remote subsystems.

The G-Link Core Interface is implemented as follows:

struct glink_core_if {
        /* Negotiation */
        void (*link_up)(struct glink_transport_if *if_ptr);
        void (*rx_cmd_version)(struct glink_transport_if *if_ptr,
                        uint32_t version,
                        uint32_t features);
        void (*rx_cmd_version_ack)(struct glink_transport_if *if_ptr,
                        uint32_t version,
                        uint32_t features);

        /* channel management */
        void (*rx_cmd_ch_remote_open)(struct glink_transport_if *if_ptr,
                        uint32_t rcid, const char *name);
        void (*rx_cmd_ch_open_ack)(struct glink_transport_if *if_ptr,
                        uint32_t lcid);
        void (*rx_cmd_ch_remote_close)(struct glink_transport_if *if_ptr,
                        uint32_t rcid);
        void (*rx_cmd_ch_close_ack)(struct glink_transport_if *if_ptr,
                        uint32_t lcid);
        void (*ch_state_local_trans)(struct glink_transport_if *if_ptr,
                        uint32_t lcid,
                        enum local_channel_state_e new_state);

        /* channel data */
        struct glink_core_rx_intent *(*rx_get_pkt_ctx)(
                        struct glink_transport_if *if_ptr,
                        uint32_t rcid, uint32_t liid);
        void (*rx_put_pkt_ctx)(struct glink_transport_if *if_ptr, uint32_t rcid,
                        struct glink_core_rx_intent *intent_ptr, bool complete);
        void (*rx_cmd_remote_rx_intent_put)(struct glink_transport_if *if_ptr,
                        uint32_t rcid, uint32_t riid, size_t size);
        void (*rx_cmd_tx_done)(struct glink_transport_if *if_ptr, uint32_t rcid,
                        uint32_t riid);
        void (*rx_cmd_remote_rx_intent_req)(struct glink_transport_if *if_ptr,
                        uint32_t rcid, size_t size);
        void (*rx_cmd_rx_intent_req_ack)(struct glink_transport_if *if_ptr,
                        uint32_t rcid, bool granted);
        void (*rx_cmd_remote_sigs)(struct glink_transport_if *if_ptr,
                        uint32_t rcid, uint32_t sigs);

        /* channel scheduling */
        void (*tx_resume)(struct glink_transport_if *if_ptr);
};

Power Management
================

Power management has yet to be implemented. See the "To do" section for more
information.

SMP/multi-core
==============

Locking and synchronization will be done using mutexes or spinlocks where
appropriate.

Security
========

No known security issues.

Performance
===========

No known performance issues.

Client Interface
================

Open
----
void *glink_open(const struct glink_open_config *cfg)

Opens a logical channel. When this function is called, a notification is sent
to the remote processor. Once the remote processor responds with an open
command, the channel will be opened locally. At this point, the channel is
considered fully open and ready for data operations. The client will be notified
at this point with a GLINK_CONNECTED notification.

When a channel is opened by calling glink_open(), a structure of configuration
information (struct glink_open_config) is passed to it. This includes the name
of the transport, the name of the edge, and the name of the channel, along with
pointers to notification functions:
 * notify_rx() - Notify the client that data has been received
 * notify_tx_done() - Notify the client that data has been transmitted
 * notify_state() - Notify the client that the channel's state has
                    changed
 * notify_rx_intent_req() - Notify the client whether their request for a
                            receive intent was granted
 * notify_rxv() - Receive notification for vector buffers
 * notify_rx_sigs() - Notification callback for change in state of remote
                      side's control signals.
 * notify_rx_abort() - During channel close, return structures associated with
                       receive intents to the client.
 * notify_tx_abort() - During channel close, return structures associated with
                       TX packets to the client.
 * notify_rx_tracer_pkt() - Receive notification for tracer packet

This structure is copied internally during the glink_open() call. The full
definition of the structure is below:

struct glink_open_config {
        unsigned options;

        const char *transport;
        const char *edge;
        const char *name;

        struct glink_ch_ctx (*notify_rx)(void *handle, const void *priv,
                        const void *pkt_priv, const void *ptr, size_t size);
        struct glink_ch_ctx (*notify_tx_done)(void *handle, const void *priv,
                        const void *pkt_priv, const void *ptr);
        struct glink_ch_ctx (*notify_state)(void *handle, const void *priv,
                        unsigned event);
        bool (*notify_rx_intent_req)(void *handle, const void *priv,
                        size_t req_size);
        struct glink_ch_ctx (*notify_rxv)(void *handle, const void *priv,
                        const void *pkt_priv, void *iovec, size_t size,
                        void *(*vbuf_provider)(void *iovec, size_t offset,
                                              size_t *size),
                        void *(*pbuf_provider)(void *iovec, size_t offset,
                                              size_t *size));
        struct glink_ch_ctx (*notify_rx_sigs)(void *handle, const void *priv,
                        uint32_t old_sigs, uint32_t new_sigs);
        struct glink_ch_ctx (*notify_rx_abort)(void *handle, const void *priv,
                        const void *pkt_priv);
        struct glink_ch_ctx (*notify_tx_abort)(void *handle, const void *priv,
                        const void *pkt_priv);
        struct glink_ch_ctx (*notify_rx_tracer_pkt)(void *handle,
                        const void *priv, const void *pkt_priv, const void *ptr,
                        size_t size);
};

The following are the possible event notification values. The GLINK_CONNECTED
notification is sent using the notify_state() callback once the channel has
been fully opened. See the Close section for the closing state details.
enum {
        GLINK_CONNECTED,
        GLINK_LOCAL_DISCONNECTED,
        GLINK_REMOTE_DISCONNECTED,
};

glink_open() returns the following standard error codes:
 * ERR_PTR(-EINVAL) - The glink_open_config structure which was passed to
                      glink_open() is invalid.
 * ERR_PTR(-ENODEV) - No transport is available.
 * ERR_PTR(-EBUSY)  - The requested channel is not ready to be re-opened.

Close
-----
int glink_close (void *handle)

Closes the logical channel. Once the close request has been processed by the
remote processor, the GLINK_LOCAL_DISCONNECTED notification is sent to the
client. If the remote processor closes the channel first, then the
GLINK_REMOTE_DISCONNECTED notification is sent to the client. After the
GLINK_LOCAL_DISCONNECTED notification is sent, no additional activity will occur
on the channel, regardless of whether the GLINK_REMOTE_DISCONNECTED notification
was sent or not. At this point, it's safe for the callbacks and/or their
resources to be destroyed. If the client wishes to re-establish communication
on the channel, then the client will need to re-open the channel.

glink_close() returns the following standard error codes:
 * -EINVAL - The channel to be closed is NULL.
 * -EBUSY  - The channel to be closed is already closing.

If the channel to be closed is already closed, 0 is returned.

Transmit Data
-------------
int glink_tx(void *handle, void *pkt_priv, void *data, size_t size,
        bool req_intent)

Arguments:
handle:     The handle returned by glink_open()
pkt_priv:   Opaque data value that will be returned to client with the
            notify_tx_done() notification
data:       Pointer to the data being sent
size:       Size of the data being sent
req_intent: Boolean indicating whether or not to request an intent from the
            remote channel

Transmit data packet for a matching RX Intent.

If a client would like to transmit a packet, but a suitable RX Intent has not
been queued, the client can request that glink_tx() block and request a
receive intent from the remote system. The remote system can still deny the
request at which point glink_tx() will return -EAGAIN to the client. The call
sequence for this exchange is:

 1. Client wants to transmit a packet, and sets the req_intent flag to true in
    the call to glink_tx() in order to request an intent if one is not already
    available.
 3. Remote G-Link calls its client's notify_rx_intent_req() function and that
    client returns a boolean indicating whether the intent will be granted or
    not
 4. If the client grants the remote intent request, glink_tx() receives the
    intent and returns success
 5. If the client rejects the remote intent request, glink_tx() returns an error

int glink_txv(void *handle, void* pkt_priv, const void *iovec, size_t size,
        glink_buffer_provider_fn vbuff_provider,
        glink_buffer_proivder_fn pbuff_provider,
        bool req_intent)

Arguments:
handle:        The handle returned by glink_open()
pkt_priv:      Opaque data value that will be returned to client with the
               notify_tx_done() notification
iovec:         Pointer to the vector
size:          Size of the data being sent
vbuf_provider: Client-provided helper function to iterate the vector in
               virtual address space
pbuf_provider: Client-provided helper function to iterate the vector in
               physical address space
req_intent:    Boolean indicating whether or not to request an intent from the
               remote channel

glink_txv() provides a transmit function that accommodates clients using vector
buffer implementations (DSM, SKB, etc.), and allows transports to operate on
virtual or physical address mappings when necessary. This is done through the
vbuf_provider() and pbuf_provider() functions, which are defined by the client
and return a pointer to the contiguous vector data after iteration. After
assembling the data from the vector, the call sequence is the same as
glink_tx().

Queue Receive Intent
--------------------
int glink_queue_rx_intent(void *handle, const void *pkt_priv, size_t size)

Queues a receive intent. A receive intent indicates that the client is ready to
receive a packet up to the specified size. The transport interface will either
reserve space for this packet or allocate a buffer to receive this packet such
that the packet can be received without stalling the physical transport.

The pkt_priv parameter is an opaque value provided by the client that is
returned in the notify_rx() callback.

Signal Consumption of Receive Buffer
------------------------------------
int glink_rx_done(void *handle, const void *ptr)

This function is called by the client to signal that they are done with the
receive buffer. The remote client is notified that it now owns the buffer again.

Set Control Signal Field
------------------------
glink_sigs_set(void *handle, uint32 *sig_value)

This function is called by the client to set a 32-bit control signal field.
Depending on the transport, it may take appropriate actions on the set bit-mask,
or transmit the entire 32-bit value to the remote host.

Get Local Control Signal Field
------------------------------
glink_sigs_local_get(void *handle, uint32 *sig_value)

This function is called by the client to retrieve the cached signals sent
using glink_sigs_set().

Get Remote Control Signal Field
-------------------------------
glink_sigs_remote_get(void *handle, uint32 *sig_value)

This function is called by the client to retrieve the cached remote signals
that were passed to notify_rx_sigs().

Register a Transport
--------------------
int glink_core_register_transport(struct glink_transport_if *if_ptr,
                                  struct glink_core_transport_cfg *cfg)

Register a new transport with the G-Link Core. The if_ptr parameter is the
interface to the transport, and the cfg parameter is the configuration, which
contains the following information:
 * The name of the transport
 * The edge of the transport, i.e. remote processor name
 * An array of the transport versions supported
 * The maximum number of entries in the versions array
 * The maximum number of channel identifiers supported
 * The maximum number of intent identifiers supported

The implementation of this transport configuration structure is below.

struct glink_core_transport_cfg {
        const char *name;
        const char *edge;
        const struct glink_core_version *versions;
        size_t versions_count;
        uint32_t max_cid;
        uint32_t max_iid;
};

The initial state of a transport after it is registered is GLINK_XPRT_DOWN.
The possible states of a transport are as follows:
enum transport_state_e {
        GLINK_XPRT_DOWN,
        GLINK_XPRT_NEGOTIATING,
        GLINK_XPRT_OPENED,
        GLINK_XPRT_FAILED,
}

Unregister a Transport
----------------------
void glink_core_unregister_transport(struct glink_transport_if *if_ptr)

Unregister/destroy an existing transport. The transport's state is changed to
GLINK_XPRT_DOWN, and the following values are reset:
 * the next local channel ID
 * The local version index
 * The remote version index
 * The version negotiation completion flag
 * The list of channels on the transport (list is deleted)

Driver parameters
=================

The G-Link core and G-Link Loopback Server modules both have a module parameter
called "debug_mask". The possible values are detailed in the "Config options"
section.

Config options
==============

G-Link supports several logging configurations. The following options are
available for the core and loopback client. They can be bitwise OR'ed together
to have multiple options at once.

QCOM_GLINK_INFO - The default option. Turn on only INFO messages
QCOM_GLINK_DEBUG - Turn on debug log messages - much more verbose logging to
                   aid in debugging.
QCOM_GLINK_PERF - Performance logging. This removes all other logging except
                  for logging messages that are created through a special
                  set of macros. These logs can be post-processed for
                  performance metrics.

The values of these options are as follows:
enum {
        QCOM_GLINK_INFO = 1U << 0,
        QCOM_GLINK_DEBUG = 1U << 1,
        QCOM_GLINK_PERF = 1U << 2,
};

Dependencies
============

IPC Logging is a dependency of the G-Link core. The Transport Plug-ins will have
their own dependencies. The SMEM Native Transport depends on SMEM and the
interrupt subsystem.

DebugFS
=======

Several DebugFS nodes are exported under the glink directory for testing and
debugging. The directory structure below allows listing information by
subsystem, channel, and transport.

glink Directory
---------------
`-- debugfs
    `-- glink
        |-- channel
        |   |-- channels <- lists all of the channels in the system, their
        |   |               state, the transport they are assigned to, etc.
        |   |-- SUBSYSTEM_NAME <- directory (such as "mpss")
        |   |   `-- CHANNEL_NAME <- one directory per channel
        |   |       |-- intents <- list of all open intents, their size, and
        |   |       |              their ID
        |   |       `-- stats <- statistics for the channel (contents TBD)
        `-- xprt
            |-- xprts <- lists all of the transports in the system and basic
            |            transport-specific state
            |-- XPRT_NAME <-- directory (such as "smem")
                `-- XPRT_INFO <-- transport specific files

User space utilities
====================

A user space driver is provided which can export a character device for a single
channel based upon Device Tree configuration. The full DT schema is detailed in
Documentation/devicetree/bindings/arm/msm/glinkpkt.txt. The user space driver
implements the standard file operations of open, release, read, write, poll, and
mmap. An ioctl is defined to queue RX intents.

The file operations map to the G-Link Client API as follows:
open()    -> glink_open() (Open a channel. Exported channels configured
                           through DT)
write()   -> glink_tx() (Transmit data)
read()    -> Receive data and send RX done notification (glink_rx_done())
release() -> glink_close() (Close a channel)
ioctl()   -> glink_queue_rx_intent()

Other operations are:
poll()    -> Poll waiting for the channel to become available
mmap()    -> Prevent having to do a copy between kernel space and user space
             for clients that need that performance.

A typical transmit and receive call flow is as follows:
1. G-Link user space driver opens the channel using open(), which returns a
   file descriptor for the channel
2. An ioctl is sent to queue an RX intent on the channel
3. Data is transmitted on the channel using write()
4. The data is received using read(). read() also sends an RX done
   notification.

Version/Feature Negotiation
===========================

To enable upgrading transports, G-Link supports a version number and feature
flags for each transport. The combination of the version number and feature
flags enable:
        1. G-Link software updates to be rolled out to each processor
           separately.
        2. Individual features to be enabled or disabled on an edge-by-edge
           basis.

Endpoints negotiate both the version and the feature flags when the transport
is opened; they cannot be changed after negotiation has been completed.

The version number represents any change in G-Link or the transport that
breaks compatibility between processors. Examples would be a change in the
shared data structures or changes to fundamental behavior in either the
transport or in G-Link Core. Each full implementation of G-Link must support a
minimum of the current version, the previous version, and the base negotiation
version called v0. For resource-constrained devices, this can be relaxed to
only support the latest version of the protocol and the v0 version.

The feature flags represent any changes in G-Link that are optional and
backwards-compatible. Feature flags can be version-specific, but to limit code
maintenance and documentation overhead, feature flags should not be re-used
unless the limit of 32 feature flags has been reached.

Negotiation Algorithm
---------------------
After a transport is registered with G-Link core, it should be configured with
the v0 transport settings. Once communication can be done without losing
messages, the link_up() call in the G-Link core should be made to start the
negotiation process. Both the local and remote sides will follow the same
negotiation state machines.

Since both sides follow the same sequence and both sides start once the link is
up, it is possible that both sides may start the negotiation sequence at the
same time resulting in a perceived race condition. However, both negotiation
sequences are independent and the transport is not considered opened until both
negotiation sequences are complete, so this is not a true race condition and
both sides will converge to the same version and feature set even if they
start with different versions and feature sets. Since this sequence is not
performance-critical, the extra complexity in the negotiation algorithm to
short-circuit the process is not deemed necessary.

Local-Initiated Negotiation Sequence
------------------------------------
The following local negotiation sequence is initiated and followed by each
side. The processor that is running this algorithm will be matched by the
remote processor following the Remote-Initiated Negotiation Sequence.

 1. Set current version and feature variables to the maximum supported version
    and feature set
 2. Send Version Command (glink_transport_if::tx_cmd_version()) with local
    version and feature set
 3. If version is 0, then negotiation has failed and the transport should be
    marked as having failed negotiation and the negotiation sequence
    terminated.
 4. When Version ACK is received (glink_core_if::rx_cmd_version_ack()):
     a. Compare ACK version to the sent version and:
         i. If equal, we are done with version negotiation
        ii. Else set current version to the lower of:
             1. Remote version number
             2. Highest supported local version
     b. Compare ACK features to the sent features and:
         i. If equal, we are done with the negotiation sequence
        ii. Else, call glink_core_version:: negotiate_features() for the
            current version to set the features to either the bitwise AND of
            the ACK features and the locally supported features or a lesser
            feature set for cases where only certain combinations of features
            are valid.
     c. Go back to step 2 to send the updated version/feature set

Remote-Initiated Negotiation Sequence
-------------------------------------
The following remote negotiation sequence is followed by each side based upon
receiving a Version Command.

 1. Receive Version Command (glink_core_if::rx_cmd_version())
 2. Compare received version with the locally supported version and:
     a. If equal, set ACK version to the received version
     b. Else, set ACK version to the lower of:
         i. Remote version number
        ii. Highest supported local version
       iii. Version 0 if no supported version less than or equal to
            the remote version number can be found.
 3. Compare received features with the locally supported features and:
     a. If equal, set ACK features to the received features
     b. Else, call glink_core_version:: negotiate_features() for the current
        version to set the features to either the bitwise AND of the ACK
        features and the locally supported features or a lesser feature set
        for cases where only certain combinations of features are valid.
 4. Send the Version ACK Command (glink_transport_if::tx_cmd_version_ack()).

Packets
=======

Packets are scheduled in a round-robin fashion from all active channels. Large
packets can be fragmented by the transport to ensure fairness between channels
and ensure latency.

Channel Migration
=================

The G-Link core has the capability of selecting the best transport available on
an edge-by-edge basis. The transport is selected based upon a pre-defined
transport priority and from optional transport selection information passed in
by the client in the glink_open_config structure.

Subsystem Restart (SSR)
=======================

In order to properly clean up channel state and recover buffer ownership
consistently across different physical transports, G-Link requires an
additional SSR notification system on top of the existing SSR framework. The
notification system is a star topology with the application processor as the
master. When a subsystem is restarted, all other subsystems are notified by the
application processor and must respond after cleaning up all affected channels
before the SSR event is allowed to continue.

The solution has four components:
 1. Target-specific configuration for each subsystem, which consists of a list
    of which subsystems should be notified in the event of SSR, specified in
    Device Tree
 2. SSR module that uses the G-Link Client API to isolate SSR functionality,
    and handles calls to the SSR Framework, Device Tree parsing, etc.
 3. SSR notification messages between the application processor and
    other subsystems, which will be exchanged using G-Link.
 4. SSR API:
     a. glink_ssr(const char *subsystem_name) - G-Link Client API
     b. ssr(struct glink_transport_if *if_ptr) - Transport Interface

1. Target-specific configuration using Device Tree
--------------------------------------------------
The target-specific configuration provides the G-Link SSR module with a list
of subsystems that should be notified in the event of SSR. This is necessary
to simplify handling of cases where there are multiple SoCs in one device -
there is no need to notify a subsystem on a second SoC of a restart in the
first SoC. The configuration also provides a mapping of the subsystem's name
in the SSR framework to its name as a G-Link edge, and allows the specification
of a transport for each notification. The figures below provide an example:

+----+      +------+        +-------------------+
|SSR |----->|G-Link|------->|Subsystem A        |
|Name|      |Name  |        |Subsystem B: xprt x|
+----+      +------+        |Subsystem C        |
                            +-------------------+

+-------+      +------+        +--------------+
|"modem"|----->|"mpss"|------->|"wcnss"       |
+-------+      +------+        |"lpass": "smd"|
                               |"dsps"        |
                               +--------------+

The above configuration tells the G-Link SSR module to notify all subsystems
on G-Link edges "wcnss", "lpass", and "dsps" that the subsystem on edge "mpss"
has restarted, and to send the notifications to the "lpass" edge on the "smd"
transport.

2. G-Link SSR Module (glink_ssr)
--------------------------------
This module is a G-Link client which handles notifications from the SSR
framework on the application processor and triggers local clean-up in response
to these notifications by calling glink_ssr(const char *subsystem). This
module also sends notifications to any subsystems that need to be notified of
the SSR event, and ensures that they respond within the standard timeout (500
ms). If the subsystem fails to respond, it is restarted.

3. G-Link SSR Messages
----------------------
When an SSR event occurs, the application processor notifies all necessary
subsystems by sending a "do_cleanup" message. After the subsystem performs the
necessary clean-up, it sends back a "cleanup_done" message. If the
"cleanup_done" message for a given subsystem is not received within the
standard timeout (500 ms), the subsystem is restarted.

SSR "do_cleanup" Message
------------------------
+-----------------+-----------------------+------------------------------+
| Element         | Type                  | Description                  |
+=================+=======================+==============================+
| version         | uint32_t              | G-Link SSR Protocol Version  |
+-----------------+-----------------------+------------------------------+
| command         | uint32_t              | do_cleanup message (0)       |
+-----------------+-----------------------+------------------------------+
| sequence_number | uint32_t              | Sequence number              |
+-----------------+-----------------------+------------------------------+
| name_len        | uint32_t              | Name length of the subsystem |
|                 |                       | being restarted              |
+-----------------+-----------------------+------------------------------+
| name            | char[GLINK_NAME_SIZE] | NULL-terminated name of the  |
|                 |                       | subsystem being restarted    |
|                 |                       | (GLINK_NAME_SIZE == 32)      |
+-----------------+-----------------------+------------------------------+

SSR "cleanup_done" Message
--------------------------
+-----------------+-----------------------+------------------------------+
| Element         | Type                  | Description                  |
+=================+=======================+==============================+
| version         | uint32_t              | G-Link SSR Protocol Version  |
+-----------------+-----------------------+------------------------------+
| response        | uint32_t              | cleanup_done message (1)     |
+-----------------+-----------------------+------------------------------+
| sequence_number | uint32_t              | Sequence number              |
+-----------------+-----------------------+------------------------------+

G-Link SSR Protocol Sequence Diagram
------------------------------------
                   +------+       +------+
+---------+        |G-Link|       |G-Link|                         +----------+
|SSR      |        |SSR   |       |Client|       +---------+       |Remote    |
|Framework|        |Module|       |API   |       |Transport|       |Processors|
+---------+        +------+       +------+       +---------+       +----------+
     |                |              |               |                  |
     | SSR            |              |               |                  |
     | Notification   |              |               |                  |
     +--------------->|              |               |                  |
     |                |              |               |                  |
     |                |              |               |                  |
     |                |              |               |                  |
     |                | do_cleanup   |               |                  |
     |                +------------------------------------------------>|
     |                |              |               |                  |
     |                | glink_ssr(subsystem)         |                  |
     |                +------------->|               |                  |
     |                |              |               |                  |
     |                |              |               |                  |
     |                |              | ssr(if_ptr)   |                  |
     |                |              +-------------->|                  |
     |                |              |               |                  |
     |                |              |               |                  |
     |                |              |               |                  |
     |                |              |               |     cleanup_done |
     |                |<------------------------------------------------+
     |                |              |               |                  |
     |                |              |               |                  |
     |                |              |               |                  |
     |  ssr(subsystem)|              |               |                  |
     |<---------------+              |               |                  |
     |                |              |               |                  |
     |    +-----------+---------+    |               |                  |
     |    |If no cleanup_done   |    |               |                  |
     |    |response is received,|    |               |                  |
     |    |restart the subsystem|    |               |                  |
     |    +-----------+---------+    |               |                  |
     |                |              |               |                  |
     |                |              |               |                  |
     |                |              |               |                  |
     |                |              |               |                  |
     |                |              |               |                  |
+---------+        +------+       +------+       +---------+       +----------+
|SSR      |        |G-Link|       |G-Link|       |Transport|       |Remote    |
|Framework|        |SSR   |       |Client|       +---------+       |Processors|
+---------+        |Module|       |API   |                         +----------+
                   +------+       +------+

4. SSR API
----------
glink_ssr(const char *subsystem_name)
-------------------------------------
Called by the G-Link SSR Module, this function calls into the transport using
ssr(struct glink_transport_if *if_ptr) to allow the transport to perform any
necessary clean-up, and simulates receiving a remote close from the restarting
subsystem for all channels on the affected edge.

ssr(struct glink_transport_if *if_ptr)
--------------------------------------
The ssr() function is part of the Transport Interface, and as mentioned above is
used to perform any necessary clean-up on the transport.

Tracer Packet Framework
=======================

A tracer packet is a special type of packet that can be used to trace the timing
of events. This helps profile the latency experienced by a packet, and provides
granular information regarding the individual latencies that make up the overall
latency. The information obtained using the tracer packet can be used to
configure the Power Management Quality of Service (PM QoS) in the system in
order to achieve a client's desired packet latency. The tracer packet moves
through the system along with other normal traffic without any impact on the
normal traffic.

When a transport is registered with the local G-Link core, it performs a
transport-specific version and feature negotiation with the remote G-Link core.
Based on this negotiation, the transport reports its capability of supporting
tracer packets to the local G-Link core.

Once the transport has successfully completed the negotiation, the clients open
the G-Link channel over the concerned transport. After the channel is open, the
clients can exchange tracer packets over G-Link, in a way similar to normal
traffic.

When a tracer packet is exchanged over a G-Link channel, the G-Link core and the
transport log events related to packet exchange and their time.

1. Tracer Packet Format
-----------------------
The tracer packet contains a header and a payload. The header contains
identification and configuration information associated with a tracer packet.
The payload contains a series of event logs. The below diagram shows the layout
of the tracer packet:

Tracer Packet Header Layout
---------------------------
 31                           16 15 14 13  12   11   4 3       0
+-------------------------------+-----+---+----+------+---------+
|      Packet Length (words)    | CCL | Q | ID | Res. | Version |
+-------------------------------+-------------------------------+
|       Client Event Cfg.       |     Packet Offset (words)     |
|           Bit Mask            |                               |
+-------------------------------+-------------------------------+
|                  G-Link Event Config Bit Mask                 |
+---------------------------------------------------------------+
|                   Base Timestamp (MS 32 bits)                 |
+---------------------------------------------------------------+
|                   Base Timestamp (LS 32 bits)                 |
+---------------------------------------------------------------+
|                         Client Cookie                         |
+---------------------------------------------------------------+

Tracer Packet Payload Layout
----------------------------
 31                           16 15                            0
+-------------------------------+-------------------------------+
|            Reserved           |          Event 1 ID           |
+-------------------------------+-------------------------------+
|                   Event 1 Timestamp (LS 32 bits)              |
+---------------------------------------------------------------+
                                .
                                .
                                .
+-------------------------------+-------------------------------+
|            Reserved           |          Event N ID           |
+-------------------------------+-------------------------------+
|                   Event N Timestamp (LS 32 bits)              |
+---------------------------------------------------------------+

Tracer Packet Header Fields
---------------------------
Version - This field contains the tracer packet version. The current version
          of tracer packet supported by G-Link is 1. If a version of the tracer
          packet is not supported by G-Link or its transport abstraction layer,
          the tracer packet is still exchanged, but no events are logged.

Reserved - The reserved bit fields are set to 0 and can be used for future
           extension of tracer packet functionality.

ID - The ID bit field indicates the presence or absence of the Source Processor
     ID, Destination Processor ID and Transport ID fields in the tracer
     packet. Currently this field is set to 0 and the concerned IDs are not
     defined.

CoreSight ("Q" in the diagram above) - This bit field is used to indicate the
                                       location of the log events. If this bit
                                       field is set, the log events are logged
                                       into CoreSight, otherwise the log events
                                       are logged into the packet itself. If the
                                       log events are logged into the packet,
                                       then the number of events logged into the
                                       packet depends on the size of the packet.

CCL - The tracer packet framework allows clients to differentiate multiple
      tracer packets through a client-specified cookie. The Client Cookie Length
      (CCL) bit field indicates the length of that cookie in units of words.

Packet Length - These 16 bits indicate the length of the tracer packet in units
                of words.

Packet Offset - This field is used when events are logged into the packet. This
                16-bit field indicates the offset into the packet, in units of
                words, to log an event. Once an event is logged, this field is
                updated with the appropriate offset to log future events.

Client Configuration Bit Mask - This bit-mask is used to enable/disable the
                                G-Link client-specific events. The procedure to
                                enable/disable client events is dependent upon
                                the client's implementation and is not included
                                in this document.

G-Link Configuration Bit Mask - This bit-mask is used to enable/disable the
                                G-Link-specific events. When a bit is set, the
                                concerned event logging is enabled.

Base Timestamp - The base timestamp contains the starting time of the tracer
                 packet exchange. The timestamp logged along with the event is
                 used as an offset from this base timestamp. This optimization
                 helps in reducing the log size of an event.

Client Cookie - The tracer packet framework allows clients to differentiate
                multiple tracer packets through a client-specified cookie.

Tracer Packet Payload Fields
----------------------------
Event ID - The Event ID field uniquely identifies the G-Link and client-specific
           tracer packet events. This field is present only when the events are
           logged into the packet. The G-Link and client event IDs are assigned
           a unique range. Refer to the table below for more information
           regarding the event ID definition.

Reserved - The reserved field is set to 0 and can be used for future extension
           of tracer packet functionality.

Event Timestamp - The Event Timestamp field contains the time at which the event
                  is logged. This field is used as an offset from the Base
                  Timestamp field in the header to calculate the actual event
                  timestamp. This field is present only when the events are
                  logged into the packet.

2. Tracer Packet Events
-----------------------
Each event has a uniquely defined ID. Since G-Link clients can use the tracer
packet framework, G-Link events and G-Link client events are defined in mutually
exclusive ranges. Since client events are client-context specific, the event
IDs can be reused among the clients. The ranges are detailed in the table below:
+--------------------------+-----------------------+
| Event Type               | Range                 |
+==========================+=======================+
| G-Link                   | 1-255                 |
+--------------------------+-----------------------+
| Client                   | 255 and above         |
+--------------------------+-----------------------+

The G-Link specific events and their associated IDs are defined in the below
table:
+--------------------------+-----------------------+
| G-Link Event             | ID                    |
+==========================+=======================+
| GLINK_CORE_TX            | 1                     |
+--------------------------+-----------------------+
| GLINK_QUEUE_TO_SCHEDULER | 2                     |
+--------------------------+-----------------------+
| GLINK_SCHEDULER_TX       | 3                     |
+--------------------------+-----------------------+
| GLINK_XPRT_TX            | 4                     |
+--------------------------+-----------------------+
| GLINK_XPRT_RX            | 5                     |
+--------------------------+-----------------------+
| GLINK_CORE_RX            | 6                     |
+--------------------------+-----------------------+

3. Tracer Packet API
--------------------
tracer_pkt_init(void *data, size_t data_len, uint16_t client_event_cfg,
            uint32_t glink_event_cfg, void *pkt_priv, size_t pkt_priv_len)
--------------------------------------------------------------------------
Initialize a buffer with the tracer packet header. The tracer packet header
includes the data passed in the parameters.

tracer_pkt_set_event_cfg(void *data, uint16_t client_event_cfg,
            uint32_t glink_event_cfg)
---------------------------------------------------------------
Initialize a buffer with the event configuration mask passed in the parameters.

tracer_pkt_log_event(void *data, uint32_t event_id)
---------------------------------------------------
Log an event specific to the tracer packet. The event is logged either into
the tracer packet itself or a different tracing mechanism as configured.

tracer_pkt_calc_hex_dump_size(void *data, size_t data_len)
----------------------------------------------------------
Calculate the length of the buffer required to hold the hex dump of the tracer
packet.

tracer_pkt_hex_dump(void *buf, size_t buf_len, void *data, size_t data_len)
---------------------------------------------------------------------------
Dump the contents of the tracer packet into a buffer in a specific hexadecimal
format. The hex dump buffer can then be dumped through debugfs.

Known issues
============

No known issues.

To do
=====

Power Management
----------------
An internal power voting API will be defined to bring the transport out of power
collapse for SMUX and BAM DMUX-type systems. In addition, power for
request/response type systems can be optimized to prevent powering down
unnecessarily after sending a request only to power up immediately to process
the response.

Round-Robin Scheduling
----------------------
Add deficit round-robin schedule to ensure fairness between channels that have
a large number of small packets and channels that are sending the maximum
MTU-sized packets.

Transport Filter Internal API
-----------------------------
An internal transport filter API will be defined. This can be plugged into a
filter chain at the transport level to easily add data coding, encryption,
integrity hashes, etc.