summaryrefslogtreecommitdiff
path: root/include/ti/cmem.h
blob: 8200b503ac927ce0c474e15332238644ac21524e (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
/*
 * Copyright (c) 2007-2018 Texas Instruments Incorporated - http://www.ti.com
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/**
 * @file    ti/cmem.h
 * @brief   Describes the interface to the contiguous memory allocator.
 *
 * The cmem user interface library wraps file system calls to an associated
 * kernel module (cmemk.ko), which needs to be loaded in order for calls to
 * this library to succeed.
 *
 * The CMEM kernel module accepts blocks of physical memory and a pool
 * geometry within those blocks.  The blocks and pools can be specified
 * either in the traditional command line method, or with the new DT
 * (Device Tree) method.  The DT method is the prefered method due to
 * its control by a system integrator.
 *
 * Command line block and pool specification
 * -----------------------------------------
 *
 * The following is an example of installing the cmem kernel module using
 * the traditional command line block and pool parameters (a DT example is
 * shown below):
 *
 * @verbatim /sbin/insmod cmemk.ko pools=4x30000,2x500000 phys_start=0x0 phys_end=0x3000000 @endverbatim
 *     - phys_start and phys_end must be specified in hexadecimal format
 *     - phys_start is "inclusive" and phys_end is "exclusive", i.e.,
 *       phys_end should be "end address + 1".
 *     - pools must be specified using decimal format (for both number and
 *       size), since using hexadecimal format would visually clutter the
 *       specification due to the use of "x" as a token separator
 *     - it's possible to insmod cmemk.ko without specifying any memory blocks,
 *       in which case CMEM_getPhys() and CMEM_cache*() APIs can still be
 *       utilized by an application, and CMA-based allocations can still be
 *       accomplished (by using blockid as CMEM_CMABLOCKID).
 *
 * This particular command creates 2 pools. The first pool is created with 4
 * buffers of size 30000 bytes and the second pool is created with 2 buffers
 * of size 500000 bytes. The CMEM pool buffers start at 0x0 and end at
 * 0x2FFFFFF (max).
 *
 * There is also support for a 2nd, 3rd, or 4th contiguous memory block to
 * be specified, with all the same features supported for those blocks as
 * with the 1st.  This 2nd block is specified with *_1 parameters (and 3rd
 * block with *_2, 4th block with *_3).  The following example expands upon
 * the first example above:
 *
 * @verbatim /sbin/insmod cmemk.ko pools=4x30000,2x500000 phys_start=0x0 phys_end=0x3000000
    pools_1=4x65536 phys_start_1=0x80000000 phys_end_1=0x80010000 @endverbatim
 *
 * This particular command, in addition to the pools explained above,
 * creates 1 pool (with 4 buffers of size 64KB) in a 2nd memory block which
 * starts at 0x80000000 and ends at 0x8000FFFF (specified as "end + 1" on the
 * insmod command).
 *
 * In order to access blocks beyond the 1st block, new APIs have been added to
 * CMEM which allow specification of the block ID.
 *
 * There is another configuration "switch" for the cmemk.ko kernel module,
 * which can be specified on the 'insmod' (or 'modprobe') command lines:
 *     useHeapIfPoolUnavailable=[0|1]
 *
 * 'useHeapIfPoolUnavailable', when set to 1, will cause pool-based allocations
 * to fallback to a heap-based allocation if no pool buffer of sufficient size
 * is available (the CMEM heap is described below).
 *
 * Pool buffers are aligned on a module-dependent boundary, and their sizes are
 * rounded up to this same boundary.  This applies to each buffer within a
 * pool.  The total space used by an individual pool will therefore be greater
 * than (or equal to) the exact amount requested in the installation of the
 * module.
 *
 * The poolid used in the driver calls would be 0 for the first pool and 1 for
 * the second pool.
 *
 * Pool allocations can be requested explicitly by pool number, or more
 * generally by just a size.  For size-based allocations, the pool which best
 * fits the requested size is automatically chosen.  Some CMEM APIs (newer
 * ones) accept a blockid as a parameter, in order to specify which of the
 * multiple blocks to operate on.  For 'legacy' APIs (ones that existed before
 * the support for multiple blocks) where a blockid is still needed, block 0
 * is assumed.
 *
 * There is also support for a general purpose heap.  In addition to the 2
 * pools described above, a general purpose heap block is created from which
 * allocations of any size can be requested.  Internally, allocation sizes are
 * rounded up to a module-dependent boundary and allocation addresses are
 * aligned either to this same boundary or to the requested alignment
 * (whichever is greater).
 *
 * The size of the heap block is the amount of CMEM memory remaining after all
 * pool allocations.  If more heap space is needed than is available after pool
 * allocations, you must reduce the amount of CMEM memory granted to the pools.
 *
 * Buffer allocation is tracked at the file descriptor level by way of a
 * 'registration' list.  The initial allocator of a buffer (the process that
 * calls CMEM_alloc()) is automatically added to the registration list,
 * and further processes can become registered for the same buffer by way
 * of the CMEM_registerAlloc() API (and unregister with the
 * CMEM_unregister() API).  This registration list for each buffer
 * allows for buffer ownership tracking and cleanup on a
 * per-file-descriptor basis, so that when a process exits or dies without
 * having explicitly freed/unregistered its buffers, they get automatically
 * unregistered (and freed when no more registered file descriptors exist).
 * Only when the last registered file descriptor frees a buffer (either
 * explictily, or by auto-cleanup) does a buffer actually get freed back to
 * the kernel module.
 *
 * Block and pool specification using Device Tree (DT)
 * ---------------------------------------------------
 *
 * The Device Tree can be used to specify physical memory blocks and pool
 * geometry within those blocks, with the same capabilities as the command
 * line specification.  DT specification is preferred over command line
 * specification for a number of reasons:
 *   - allows specifying the physical "carveout" with direct linkage to
 *     that carveout in the pool specification, thereby eliminating potential
 *     errors that could occur when the physical carveout is defined in one
 *     place and then needing to be specified on the cmemk.ko command line
 *     exactly equivalent to the carveout definition.
 *   - allows a system integrator to define the CMEM specifications without
 *     the need to document instructions for the command line, or prepackage
 *     the command line in some filesystem-based script.
 *
 * CMEM allows both DT-specified and command line specified blocks.  Each
 * block is assigned a number that can be later used for allocations in
 * order to direct the allocation to a particular block.  This allows some
 * blocks to be defined in the DT and other blocks to be later defined
 * on the CMEM command line.  If a particular block number is assigned in
 * DT and also specified on the CMEM command line then the DT specification
 * takes precedence and the command line specification is ignored.
 *
 * The following DT example snippet illustrates the syntax...
 *
 * @code 
 * // Specify reserved physical blocks, using "no-map" to keep Linux away.
 * // The "reg" property is the base address and size in 32-bit ints.
 * // This is the generic "reserved-memory" node that might also contain
 * // other non-CMEM entries.
 *
 *      reserved-memory {
 *              #address-cells = <1>;
 *              #size-cells = <1>;
 *              ranges;
 *      ...
 *              cmem_block_mem_0: cmem_block_mem@a0000000 {
 *                      reg = <0xa0000000 0x10000000>;
 *                      no-map;
 *                      status = "okay";
 *              };
 *
 *              cmem_block_mem_1: cmem_block_mem@b0000000 {
 *                      reg = <0xb0000000 0x02000000>;
 *                      no-map;
 *                      status = "okay";
 *              };
 *      };
 *
 * // The CMEM node is specified below, and can be named arbitrarily ("cmem"
 * // name chosen here).  The node's "compatible" property must contain
 * // "ti,cmem" in order for CMEM to process it.
 *
 *      cmem {
 *              compatible = "ti,cmem";  // must be "ti,cmem"
 *              #address-cells = <1>;
 *              #size-cells = <0>;
 *
 *              status = "okay";
 *
 * // CMEM block specifications along with pool geometry.
 * //
 * // The "reg" property is the block identifier, and each child of the
 * // cmem node must specify a different "reg" value.  The domain of
 * // the block identifier is 0 -> <nblocks - 1>, where nblocks is the
 * // total amount of DT-specified and command line-specified blocks.
 * // CMEM currently supports up to 4 blocks (although that can be increased
 * // by simple comment-directed modifications in cmemk.c).
 * //
 * // The "memory-region" property points to the phandle of the
 * // reserved-memory area.
 * //
 * // The "cmem-buf-pools" property contains a variable number of comma-
 * // separated pools, with each pool specifying the number of buffers and
 * // the size of each buffer in <n size> format.
 *
 *              cmem_block_0: cmem_block@0 {
 *                      reg = <0>;
 *                      memory-region = <&cmem_block_mem_0>;
 *                      cmem-buf-pools = <1 0x0c000000>, <4 0x01000000>; // 1x192MB, 4x16MB pools
 *              };
 *
 *              cmem_block_1: cmem_block@1 {
 *                      reg = <1>;
 *                      memory-region = <&cmem_block_mem_1>;
 *                      cmem-buf-pools = <1 0x02000000>; // 1x32MB pool, remaining carveout is heap.
 *              };
 *      };
 * @endcode
 *
 * Decoupled allocation & memory mapping
 * -------------------------------------
 *
 * For every CMEM_alloc*() API, there is a corresponding "Phys" API that
 * returns the physical address of the allocation and does *not* do the
 * user-space memory mapping (mmap()).  There is also a corresponding
 * CMEM_freePhys() to be used for freeing allocations performed by the
 * "Phys" APIs.  The user-space memory mapping is performed with the
 * CMEM_map()/CMEM_unmap() APIs.  This allows large buffer allocations
 * without the burden of using up a large portion of the application's
 * virtual address space for the duration of the allocation's existence.
 * A mapping performed by CMEM_map() doesn't have to be for the whole of
 * the allocated buffer, it can be for just portions of the buffer (but
 * must not be larger than the allocated buffer).
 *
 * CMEM_map() can be called multiple times for the same physical allocation.
 * Each invocation of CMEM_map() will allocate a new user virtual address
 * range for the same physical allocation.
 *
 * CMA access
 * ----------
 *
 * On systems with CMA (Contiguous Memory Allocator) support, CMEM can be used
 * to allocate CMA buffers.  Both heap and pool allocations are supported.  A
 * special block ID, CMEM_CMABLOCKID, is used for these allocations, and
 * therefore the block-based CMEM APIs must be used (the ones ending in "2",
 * such as CMEM_alloc2()), where the 'blockid' parameter is CMEM_CMABLOCKID
 * (instead of 0 or 1).
 *
 * CMA always contains, at the minimum, a global area that can be accessed
 * by any device driver.  CMEM treats this global area as a heap, which means
 * that heap-based allocations can be performed on CMEM_CMABLOCKID.
 * See the Linux CMA documentation for details on specifying this global area.
 * Keep in mind that other Linux kernel entities can (and will) also allocate
 * memory from this global area, so you never really know how much is
 * available for allocations by CMEM.
 *
 * To achieve pool-based allocations from CMA, a special CMEM stub must be
 * builtin to the kernel, and CMEM must be built with CMEM_KERNEL_STUB=1 for
 * the 'make' command (which turns into -DCMEM_KERNEL_STUB on the compile
 * command).  This stub processes a kernel command line parameter named
 * "cmem_cma_pools=..." in the same fashion as the standard CMEM "pools=...".
 * A separate CMA region (area) is created for each of the separate
 * "cmem_cma_pools" (where each pool/region is one element of the comma-
 * separated list).
 *
 * The CMEM builtin kernel stub is located in
 *     .../src/cmem/module/kernel/drivers/cmem/cmemk_stub.c
 * You don't need this stub if you want to allocate only from the CMA
 * global area.  Please see comments at the head of the above file for
 * instructions on how to incorporate it into your kernel.
 *
 * In supporting the pool model of CMEM, a separate CMA region is created for
 * each pool.  A pool consists of n buffers of size s, resulting in a region
 * that is sized accordingly.  CMA places no restrictions on the size of an
 * allocation from a region, so the buffer size 's' becomes more of a
 * convention than a hard rule.  Given enough free space, any pool can be
 * used to allocate a buffer of any size, but it is recommended to partition
 * regions (or, in this case, pools) according to the size of buffers that
 * will be allocated in order to reduce fragmentation and wasted memory due
 * to size-based alignment padding.  In other words, if your system will be
 * allocating 10 buffers of size 4096, 8 of size 131072, and 4 of size
 * 1048576, create pools of
 *     cmem_cma_pools=10x4096,8x131072,4x1048576
 * and perform allocations from the respective pool.
 *
 * An application doesn't need to know the pool IDs that correspond to the
 * respective sizes of that pool's buffers.  The CMEM_alloc2() API decides
 * which pool to use according to the requested size of allocation, and will
 * choose the one that fits most efficiently.  Unlike non-CMA pool allocations
 * where, when the "best fit" pool has no remaining buffers it will choose a
 * pool with larger available buffers, CMEM_alloc2() won't "promote" a
 * CMA-based pool allocation to a pool with buffers larger than the the best
 * fit.
 *
 * CMEM supports a kernel command line parameter named "cmem_cma_heapsize".
 * When assigned, a CMA region of size "cmem_cma_heapsize" is created for use
 * by CMEM heap allocations for the CMA "block".  This heap is then used for
 * CMEM CMA heap allocations, and the CMA global area is no longer used by
 * CMEM.  This allows CMEM to have full usage of the CMEM CMA heap without
 * possible allocations by non-CMEM entities in the kernel.
 */
/**
 *  @defgroup   ti_CMEM  Contiguous Memory Manager
 *
 *  @copydoc ti/cmem.h
 */

#ifndef ti_CMEM_H
#define ti_CMEM_H

#if defined (__cplusplus)
extern "C" {
#endif

/** @ingroup    ti_CMEM */
/*@{*/

#define CMEM_VERSION    0x04200000U

#define MAX_POOLS 32

/* magic "block" corresponding to CMA regions */
#define CMEM_CMABLOCKID			-1

/* ioctl cmd "flavors" */
#define CMEM_WB				0x00010000
#define CMEM_INV			0x00020000
#define CMEM_HEAP			0x00040000  /**< operation applies to heap */
#define CMEM_POOL			0x00000000  /**< operation applies to a pool */
#define CMEM_CACHED			0x00080000  /**< allocated buffer is cached */
#define CMEM_NONCACHED			0x00000000  /**< allocated buffer is not cached */
#define CMEM_PHYS			0x00100000

#define CMEM_IOCMAGIC			0x0000fe00

/* supported "base" ioctl cmds for the driver. */
#define CMEM_IOCALLOC                   1
#define CMEM_IOCALLOCHEAP               2
#define CMEM_IOCFREE                    3
#define CMEM_IOCGETPHYS                 4
#define CMEM_IOCGETSIZE                 5
#define CMEM_IOCGETPOOL                 6
#define CMEM_IOCCACHE                   7
#define CMEM_IOCGETVERSION              8
#define CMEM_IOCGETBLOCK                9
#define CMEM_IOCREGUSER                 10
#define CMEM_IOCGETNUMBLOCKS            11
#define CMEM_IOCCACHEWBINVALL           12
#define CMEM_IOCEXPORTDMABUF            13
/*
 * New ioctl cmds should use integers greater than the largest current cmd
 * in order to not break backward compatibility.
 */

/* supported "flavors" to "base" ioctl cmds for the driver. */
#define CMEM_IOCCACHEWBINV              CMEM_IOCCACHE | CMEM_WB | CMEM_INV
#define CMEM_IOCCACHEWB                 CMEM_IOCCACHE | CMEM_WB
#define CMEM_IOCCACHEINV                CMEM_IOCCACHE | CMEM_INV
#define CMEM_IOCALLOCCACHED             CMEM_IOCALLOC | CMEM_CACHED
#define CMEM_IOCALLOCHEAPCACHED         CMEM_IOCALLOCHEAP | CMEM_CACHED
#define CMEM_IOCFREEHEAP                CMEM_IOCFREE | CMEM_HEAP
#define CMEM_IOCFREEPHYS                CMEM_IOCFREE | CMEM_PHYS
#define CMEM_IOCFREEHEAPPHYS            CMEM_IOCFREE | CMEM_HEAP | CMEM_PHYS

#define CMEM_IOCCMDMASK			0x000000ff

/**
 * @brief Parameters for CMEM_alloc(), CMEM_alloc2(), CMEM_allocPool(),
 * CMEM_allocPool2(), CMEM_free().
 */
typedef struct CMEM_AllocParams {
    int type;		/**< either #CMEM_HEAP or #CMEM_POOL */
    int flags;		/**< either #CMEM_CACHED or #CMEM_NONCACHED */
    size_t alignment;	/**<
                         * only used for heap allocations, must be power of 2
                         */
} CMEM_AllocParams;

struct CMEM_block_struct {
    void *addr;
    size_t size;
};

struct CMEM_dmabufDesc {
	void *virtp;
	int fd_dmabuf;
};

extern CMEM_AllocParams CMEM_DEFAULTPARAMS;

typedef struct CMEM_BlockAttrs {
    off_t phys_base;
    unsigned long long size;
} CMEM_BlockAttrs;

/** @cond INTERNAL */

/**
 */
union CMEM_AllocUnion {
    struct {			/**< */
	size_t size;
	size_t align;
	int blockid;
    } alloc_heap_inparams;	/**< */
    struct {			/**< */
	int poolid;
	int blockid;
    } alloc_pool_inparams;	/**< */
    struct {			/**< */
	int poolid;
	int blockid;
    } get_size_inparams;	/**< */
    struct {			/**< */
	unsigned long long size;
	int blockid;
    } get_pool_inparams;	/**< */
    struct {			/**< */
	unsigned long long physp;
	unsigned long long size;
    } alloc_pool_outparams;	/**< */
    struct {			/**< */
	unsigned long long physp;
	unsigned long long size;
    } get_block_outparams;	/**< */
    struct {			/**< */
	int poolid;
	size_t size;
    } free_outparams;		/**< */
    unsigned long long physp;
    void *virtp;
    size_t size;
    int poolid;
    int blockid;
};

/** @endcond */

/**
 * @brief Initialize the CMEM module. Must be called before other API calls.
 *
 * @return 0 for success or -1 for failure.
 *
 * @sa CMEM_exit
 */
int CMEM_init(void);

/**
 * @brief Find the pool that best fits a given buffer size and has a buffer
 * available.
 *
 * @param   size    The buffer size for which a pool is needed.
 *
 * @return A poolid that can be passed to CMEM_allocPool(), or -1 for error.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_allocPool()
 * @sa CMEM_allocPool2()
 * @sa CMEM_free()
 * @sa CMEM_getPool2()
 */
int CMEM_getPool(unsigned long long size);

/**
 * @brief Find the pool in memory block blockid that best fits a given
 * buffer size and has a buffer available.
 *
 * @param   blockid  Block number
 * @param   size     The buffer size for which a pool is needed.
 *
 * @return A poolid that can be passed to CMEM_allocPool2(), or -1 for error.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_allocPool()
 * @sa CMEM_allocPool2()
 * @sa CMEM_free()
 * @sa CMEM_getPool()
 */
int CMEM_getPool2(int blockid, unsigned long long size);

/**
 * @brief Allocate memory from a specified pool.
 *
 * @param   poolid  The pool from which to allocate memory.
 * @param   params  Allocation parameters.
 *
 * @remarks @c params->type is ignored - a pool will always be used.
 * @remarks @c params->alignment is unused, since pool buffers are already
 *          aligned to specific boundaries.
 *
 * @return A pointer to the allocated buffer, or NULL for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_alloc()
 * @sa CMEM_alloc2()
 * @sa CMEM_allocPool2()
 * @sa CMEM_registerAlloc()
 * @sa CMEM_unregister()
 * @sa CMEM_free()
 */
void *CMEM_allocPool(int poolid, CMEM_AllocParams *params);

/**
 * @brief Allocate memory from a specified pool in a specified memory block.
 *
 * @param   blockid The memory block from which to allocate.
 * @param   poolid  The pool from which to allocate memory.
 * @param   params  Allocation parameters.
 *
 * @remarks @c params->type is ignored - a pool will always be used.
 * @remarks @c params->alignment is unused, since pool buffers are already
 *          aligned to specific boundaries.
 *
 * @return A pointer to the allocated buffer, or NULL for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_alloc()
 * @sa CMEM_alloc2()
 * @sa CMEM_allocPool()
 * @sa CMEM_registerAlloc()
 * @sa CMEM_unregister()
 * @sa CMEM_free()
 */
void *CMEM_allocPool2(int blockid, int poolid, CMEM_AllocParams *params);

/**
 * @brief Allocate memory of a specified size
 *
 * @param   size    The size of the buffer to allocate.
 * @param   params  Allocation parameters.
 *
 * @remarks Used to allocate memory from either a pool, the heap, or the CMA
 *          global area.
 *          If doing a pool allocation, the pool that best fits the requested
 *          size will be selected.  Use CMEM_allocPool() to allocate from a
 *          specific pool.
 *          Allocation will be cached or noncached, as specified by params.
 *          params->alignment valid only for heap allocation.
 *
 * @return A pointer to the allocated buffer, or NULL for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_allocPool()
 * @sa CMEM_allocPool2()
 * @sa CMEM_alloc2()
 * @sa CMEM_registerAlloc()
 * @sa CMEM_unregister()
 * @sa CMEM_free()
 */
void *CMEM_alloc(size_t size, CMEM_AllocParams *params);

/**
 * @brief Allocate memory of a specified size from a specified memory block
 *
 * @param   blockid The memory block from which to allocate.
 * @param   size    The size of the buffer to allocate.
 * @param   params  Allocation parameters.
 *
 * @remarks Used to allocate memory from either a pool, the heap, or the CMA
 *          global area.
 *          If doing a pool allocation, the pool that best fits the requested
 *          size will be selected.  Use CMEM_allocPool() to allocate from a
 *          specific pool.
 *
 * @remarks Allocation will be cached or noncached, as specified by params.
 *          params->alignment valid only for heap allocation.
 *
 * @return A pointer to the allocated buffer, or NULL for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_allocPool()
 * @sa CMEM_allocPool2()
 * @sa CMEM_alloc()
 * @sa CMEM_registerAlloc()
 * @sa CMEM_unregister()
 * @sa CMEM_free()
 */
void *CMEM_alloc2(int blockid, size_t size, CMEM_AllocParams *params);

/**
 * @brief Allocate unmapped memory from a specified pool.
 *
 * @param   poolid  The pool from which to allocate memory.
 * @param   params  Allocation parameters.
 *
 * @remarks @c params->type is ignored - a pool will always be used.
 * @remarks @c params->alignment is unused, since pool buffers are already
 *          aligned to specific boundaries.
 *
 * @return The physical address of the allocated buffer, or NULL for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_allocPhys()
 * @sa CMEM_allocPhys2()
 * @sa CMEM_allocPoolPhys2()
 * @sa CMEM_freePhys()
 * @sa CMEM_map()
 */
off_t CMEM_allocPoolPhys(int poolid, CMEM_AllocParams *params);

/**
 * @brief Allocate unmapped memory from a specified pool in a specified
 *        memory block.
 *
 * @param   blockid The memory block from which to allocate.
 * @param   poolid  The pool from which to allocate memory.
 * @param   params  Allocation parameters.
 *
 * @remarks @c params->type is ignored - a pool will always be used.
 * @remarks @c params->alignment is unused, since pool buffers are already
 *          aligned to specific boundaries.
 *
 * @return The physical address of the allocated buffer, or NULL for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_allocPhys()
 * @sa CMEM_allocPhys2()
 * @sa CMEM_allocPoolPhys()
 * @sa CMEM_freePhys()
 * @sa CMEM_map()
 */
off_t CMEM_allocPoolPhys2(int blockid, int poolid, CMEM_AllocParams *params);

#if defined(LINUXUTILS_BUILDOS_ANDROID)
/**
 * @brief Allocate unmapped memory from a specified pool in a specified
 *        memory block (Android only).
 *
 * @param   blockid The memory block from which to allocate.
 * @param   poolid  The pool from which to allocate memory.
 * @param   params  Allocation parameters.
 *
 * @remarks @c params->type is ignored - a pool will always be used.
 * @remarks @c params->alignment is unused, since pool buffers are already
 *          aligned to specific boundaries.
 *
 * @return The physical address of the allocated buffer, or NULL for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_allocPhys()
 * @sa CMEM_allocPhys2()
 * @sa CMEM_allocPoolPhys()
 * @sa CMEM_freePhys()
 * @sa CMEM_map()
 */
off64_t CMEM_allocPoolPhys64(int blockid, int poolid, CMEM_AllocParams *params);
#endif

/**
 * @brief Allocate unmapped memory of a specified size
 *
 * @param   size    The size of the buffer to allocate.
 * @param   params  Allocation parameters.
 *
 * @remarks Used to allocate memory from either a pool, the heap, or the CMA
 *          global area.
 *          If doing a pool allocation, the pool that best fits the requested
 *          size will be selected.  Use CMEM_allocPool() to allocate from a
 *          specific pool.
 *          Allocation will be cached or noncached, as specified by params.
 *          params->alignment valid only for heap allocation.
 *
 * @return The physical address of the allocated buffer, or NULL for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_allocPoolPhys()
 * @sa CMEM_allocPoolPhys2()
 * @sa CMEM_allocPhys2()
 * @sa CMEM_freePhys()
 * @sa CMEM_map()
 */
off_t CMEM_allocPhys(size_t size, CMEM_AllocParams *params);

/**
 * @brief Allocate unmapped memory of a specified size from a specified
 *        memory block
 *
 * @param   blockid The memory block from which to allocate.
 * @param   size    The size of the buffer to allocate.
 * @param   params  Allocation parameters.
 *
 * @remarks Used to allocate memory from either a pool, the heap, or the CMA
 *          global area.
 *          If doing a pool allocation, the pool that best fits the requested
 *          size will be selected.  Use CMEM_allocPool() to allocate from a
 *          specific pool.
 *
 * @remarks Allocation will be cached or noncached, as specified by params.
 *          params->alignment valid only for heap allocation.
 *
 * @return The physical address of the allocated buffer, or NULL for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_allocPoolPhys()
 * @sa CMEM_allocPoolPhys2()
 * @sa CMEM_allocPhys()
 * @sa CMEM_freePhys()
 * @sa CMEM_map()
 */
off_t CMEM_allocPhys2(int blockid, size_t size, CMEM_AllocParams *params);

#if defined(LINUXUTILS_BUILDOS_ANDROID)
/**
 * @brief Allocate unmapped memory of a specified size from a specified
 *        memory block (Android only)
 *
 * @param   blockid The memory block from which to allocate.
 * @param   size    The size of the buffer to allocate.
 * @param   params  Allocation parameters.
 *
 * @remarks Used to allocate memory from either a pool, the heap, or the CMA
 *          global area.
 *          If doing a pool allocation, the pool that best fits the requested
 *          size will be selected.  Use CMEM_allocPool() to allocate from a
 *          specific pool.
 *
 * @remarks Allocation will be cached or noncached, as specified by params.
 *          params->alignment valid only for heap allocation.
 *
 * @return The physical address of the allocated buffer, or NULL for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_allocPoolPhys()
 * @sa CMEM_allocPoolPhys2()
 * @sa CMEM_allocPhys()
 * @sa CMEM_freePhys()
 * @sa CMEM_map()
 */
off64_t CMEM_allocPhys64(int blockid, size_t size, CMEM_AllocParams *params);
#endif

/**
 * @brief Register shared usage of an already-allocated buffer
 *
 * @param   physp  Physical address of the already-allocated buffer.
 *
 * @remarks Used to register the calling process for usage of an
 *          already-allocated buffer, for the purpose of shared usage of
 *          the buffer.
 *
 * @remarks Allocation properties (such as cached/noncached or heap/pool)
 *          are inherited from original allocation call.
 *
 * @return  A process-specific pointer to the allocated buffer, or NULL
 *          for failure.
 *
 * @pre Must have called some form of CMEM_alloc*()
 *
 * @sa CMEM_allocPool()
 * @sa CMEM_allocPool2()
 * @sa CMEM_alloc()
 * @sa CMEM_free()
 * @sa CMEM_unregister()
 */
void *CMEM_registerAlloc(off_t physp);

#if defined(LINUXUTILS_BUILDOS_ANDROID)
/**
 * @brief Register shared usage of an already-allocated buffer using mmap64
 *        (Android only)
 *
 * @param   physp  Physical address of the already-allocated buffer.
 *
 * @remarks Used to register the calling process for usage of an
 *          already-allocated buffer, for the purpose of shared usage of
 *          the buffer.
 *
 * @remarks Allocation properties (such as cached/noncached or heap/pool)
 *          are inherited from original allocation call.
 *
 * @return  A process-specific pointer to the allocated buffer, or NULL
 *          for failure.
 *
 * @pre Must have called some form of CMEM_alloc*()
 *
 * @sa CMEM_allocPool()
 * @sa CMEM_allocPool2()
 * @sa CMEM_alloc()
 * @sa CMEM_free()
 * @sa CMEM_unregister()
 */
void *CMEM_registerAlloc64(off64_t physp);
#endif

/**
 * @brief Free a buffer previously allocated with
 *        CMEM_alloc()/CMEM_allocPool().
 *
 * @param   ptr     The pointer to the buffer.
 * @param   params  Allocation parameters.
 *
 * @remarks Use the same CMEM_AllocParams as was used for the allocation.
 *          params->flags is "don't care".  params->alignment is "don't
 *          care".
 *
 * @return 0 for success or -1 for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_alloc()
 * @sa CMEM_alloc2()
 * @sa CMEM_allocPool()
 * @sa CMEM_allocPool2()
 * @sa CMEM_registerAlloc()
 * @sa CMEM_unregister()
 */
int CMEM_free(void *ptr, CMEM_AllocParams *params);

/**
 * @brief Free an unmapped buffer previously allocated with
 *        CMEM_allocPhys()/CMEM_allocPoolPhys().
 *
 * @param   physp   The physical address of the buffer.
 * @param   params  Allocation parameters.
 *
 * @remarks Use the same CMEM_AllocParams as was used for the allocation.
 *          params->flags is "don't care".  params->alignment is "don't
 *          care".
 *
 * @return 0 for success or -1 for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_allocPhys()
 * @sa CMEM_allocPhys2()
 * @sa CMEM_allocPoolPhys()
 * @sa CMEM_allocPoolPhys2()
 * @sa CMEM_unmap()
 */
int CMEM_freePhys(off_t physp, CMEM_AllocParams *params);

#if defined(LINUXUTILS_BUILDOS_ANDROID)
/**
 * @brief Free an unmapped buffer previously allocated with
 *        CMEM_allocPhys64()/CMEM_allocPoolPhys64() (Android only).
 *
 * @param   physp   The physical address of the buffer.
 * @param   params  Allocation parameters.
 *
 * @remarks Use the same CMEM_AllocParams as was used for the allocation.
 *          params->flags is "don't care".  params->alignment is "don't
 *          care".
 *
 * @return 0 for success or -1 for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_allocPhys()
 * @sa CMEM_allocPhys2()
 * @sa CMEM_allocPoolPhys()
 * @sa CMEM_allocPoolPhys2()
 * @sa CMEM_unmap()
 */
int CMEM_freePhys64(off64_t physp, CMEM_AllocParams *params);
#endif

/**
 * @brief Unregister use of a buffer previously registered with
 *        CMEM_registerAlloc().
 *
 * @param   ptr     The pointer to the buffer.
 * @param   params  Allocation parameters.
 *
 * @remarks Use the same CMEM_AllocParams as was used for the allocation.
 *          params->flags is "don't care".  params->alignment is "don't
 *          care".
 *
 * @return 0 for success or -1 for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_alloc()
 * @sa CMEM_alloc2()
 * @sa CMEM_allocPool()
 * @sa CMEM_allocPool2()
 * @sa CMEM_registerAlloc()
 * @sa CMEM_free()
 */
int CMEM_unregister(void *ptr, CMEM_AllocParams *params);

/**
 * @brief Get the physical address of a contiguous buffer.
 *
 * @param   ptr     The pointer to the buffer.
 *
 * @return The physical address of the buffer or 0 for failure.
 *
 * @pre Must have called CMEM_init()
 */
off_t CMEM_getPhys(void *ptr);

#if defined(LINUXUTILS_BUILDOS_ANDROID)
/**
 * @brief Get the physical address of a contiguous buffer (Android only).
 *
 * @param   ptr     The pointer to the buffer.
 *
 * @return The physical address of the buffer or 0 for failure.
 *
 * @pre Must have called CMEM_init()
 */
off64_t CMEM_getPhys64(void *ptr);
#endif

/**
 * @brief Do a cache writeback/invalidate of the whole cache
 *
 * @return Success/failure boolean value
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_cacheWb()
 * @sa CMEM_cacheInv()
 * @sa CMEM_cacheWbInv()
 */
int CMEM_cacheWbInvAll(void);

/**
 * @brief Do a cache writeback of the block pointed to by @c ptr/@c size
 *
 * @param   ptr     Pointer to block to writeback
 * @param   size    Size in bytes of block to writeback.
 *
 * @return Success/failure boolean value
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_cacheInv()
 * @sa CMEM_cacheWbInv()
 * @sa CMEM_cacheWbInvAll()
 */
int CMEM_cacheWb(void *ptr, size_t size);

/**
 * @brief Map allocated memory
 *
 * @param   physp   Physical address of the already-allocated buffer.
 * @param   size    Size in bytes of block to map.
 *
 * @return A pointer to the mapped buffer, or NULL for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_allocPhys()
 * @sa CMEM_allocPoolPhys()
 * @sa CMEM_unmap()
 */
void *CMEM_map(off_t physp, size_t size);

#if defined(LINUXUTILS_BUILDOS_ANDROID)
/**
 * @brief Map allocated memory using mmap64 (Android only)
 *
 * @param   physp   Physical address of the already-allocated buffer.
 * @param   size    Size in bytes of block to map.
 *
 * @return A pointer to the mapped buffer, or NULL for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_allocPhys()
 * @sa CMEM_allocPoolPhys()
 * @sa CMEM_unmap()
 */
void *CMEM_map64(off64_t physp, size_t size);
#endif

/**
 * @brief Unmap allocated memory
 *
 * @param   userp   User virtual address of the mapped buffer.
 * @param   size    Size in bytes of block to unmap.
 *
 * @return Success/failure boolean value
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_freePhys()
 * @sa CMEM_map()
 */
int CMEM_unmap(void *userp, size_t size);

/**
 * @brief Do a cache invalidate of the block pointed to by @c ptr/@c size
 *
 * @param   ptr     Pointer to block to invalidate
 * @param   size    Size in bytes of block to invalidate
 *
 * @return Success/failure boolean value
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_cacheWb()
 * @sa CMEM_cacheWbInv()
 * @sa CMEM_cacheWbInvAll()
 */
int CMEM_cacheInv(void *ptr, size_t size);

/**
 * @brief Do a cache writeback/invalidate of the block pointed to by
 *        @c ptr/@c size
 *
 * @param   ptr     Pointer to block to writeback/invalidate
 * @param   size    Size in bytes of block to writeback/invalidate
 *
 * @return Success/failure boolean value
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_cacheInv()
 * @sa CMEM_cacheWb()
 * @sa CMEM_cacheWbInvAll()
 */
int CMEM_cacheWbInv(void *ptr, size_t size);

/**
 * @brief Retrieve version from CMEM driver.
 *
 * @return Installed CMEM driver's version number.
 *
 * @pre Must have called CMEM_init()
 */
int CMEM_getVersion(void);

/**
 * @brief Retrieve memory block bounds from CMEM driver
 *
 * @param   pphys_base   Pointer to storage for base physical address of
 *                       CMEM's memory block
 * @param   psize        Pointer to storage for size of CMEM's memory block
 *
 * @return Success (0) or failure (-1).
 *
 * @pre Must have called CMEM_init()
 *
 * @sa  CMEM_getBlockAttrs()
 * @sa  CMEM_getNumBlocks()
 */
int CMEM_getBlock(off_t *pphys_base, unsigned long long *psize);

/**
 * @brief Retrieve extended memory block attributes from CMEM driver
 *
 * @param   blockid      Block number
 * @param   pattrs       Pointer to CMEM_BlockAttrs struct
 *
 * @return Success (0) or failure (-1).
 *
 * @remarks Currently this API returns the same values as CMEM_getBlock().
 *
 * @pre Must have called CMEM_init()
 *
 * @sa  CMEM_getBlock()
 * @sa  CMEM_getNumBlocks()
 */
int CMEM_getBlockAttrs(int blockid, CMEM_BlockAttrs *pattrs);

/**
 * @brief Retrieve number of blocks configured into CMEM driver
 *
 * @param   pnblocks     Pointer to storage for holding number of blocks
 *
 * @return Success (0) or failure (-1).
 *
 * @remarks Blocks are configured into CMEM through the Linux 'insmod'
 *          command.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa  CMEM_getBlock()
 * @sa  CMEM_getBlockAttrs()
 */
int CMEM_getNumBlocks(int *pnblocks);

/**
 * @brief export as dma_buf a buffer previously allocated with
 *        CMEM_alloc()/CMEM_allocPool().
 *
 * @param   ptr     The pointer to the buffer.
 *
 *
 * @return 0 for success or -1 for failure.
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_alloc()
 * @sa CMEM_alloc2()
 * @sa CMEM_allocPool()
 * @sa CMEM_allocPool2()
 * @sa CMEM_registerAlloc()
 * @sa CMEM_unregister()
 */

int CMEM_export_dmabuf(void *ptr);

/**
 * @brief Finalize the CMEM module.
 *
 * @return 0 for success or -1 for failure.
 *
 * @remarks After this function has been called, no other CMEM function may be
 *          called (unless CMEM is reinitialized).
 *
 * @pre Must have called CMEM_init()
 *
 * @sa CMEM_init()
 */
int CMEM_exit(void);

/*@}*/

#if defined (__cplusplus)
}
#endif

#endif