1*053f45beSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0
2*053f45beSAndroid Build Coastguard Worker
3*053f45beSAndroid Build Coastguard Worker #include <dirent.h>
4*053f45beSAndroid Build Coastguard Worker #include <errno.h>
5*053f45beSAndroid Build Coastguard Worker #include <fcntl.h>
6*053f45beSAndroid Build Coastguard Worker #include <stdio.h>
7*053f45beSAndroid Build Coastguard Worker #include <stdlib.h>
8*053f45beSAndroid Build Coastguard Worker #include <stdint.h>
9*053f45beSAndroid Build Coastguard Worker #include <string.h>
10*053f45beSAndroid Build Coastguard Worker #include <unistd.h>
11*053f45beSAndroid Build Coastguard Worker #include <sys/ioctl.h>
12*053f45beSAndroid Build Coastguard Worker #include <sys/mman.h>
13*053f45beSAndroid Build Coastguard Worker #include <sys/types.h>
14*053f45beSAndroid Build Coastguard Worker
15*053f45beSAndroid Build Coastguard Worker #include <linux/dma-buf.h>
16*053f45beSAndroid Build Coastguard Worker #include <drm/drm.h>
17*053f45beSAndroid Build Coastguard Worker
18*053f45beSAndroid Build Coastguard Worker #include "../../../../include/uapi/linux/dma-heap.h"
19*053f45beSAndroid Build Coastguard Worker
20*053f45beSAndroid Build Coastguard Worker #define DEVPATH "/dev/dma_heap"
21*053f45beSAndroid Build Coastguard Worker
check_vgem(int fd)22*053f45beSAndroid Build Coastguard Worker static int check_vgem(int fd)
23*053f45beSAndroid Build Coastguard Worker {
24*053f45beSAndroid Build Coastguard Worker drm_version_t version = { 0 };
25*053f45beSAndroid Build Coastguard Worker char name[5];
26*053f45beSAndroid Build Coastguard Worker int ret;
27*053f45beSAndroid Build Coastguard Worker
28*053f45beSAndroid Build Coastguard Worker version.name_len = 4;
29*053f45beSAndroid Build Coastguard Worker version.name = name;
30*053f45beSAndroid Build Coastguard Worker
31*053f45beSAndroid Build Coastguard Worker ret = ioctl(fd, DRM_IOCTL_VERSION, &version);
32*053f45beSAndroid Build Coastguard Worker if (ret)
33*053f45beSAndroid Build Coastguard Worker return 0;
34*053f45beSAndroid Build Coastguard Worker
35*053f45beSAndroid Build Coastguard Worker return !strcmp(name, "vgem");
36*053f45beSAndroid Build Coastguard Worker }
37*053f45beSAndroid Build Coastguard Worker
open_vgem(void)38*053f45beSAndroid Build Coastguard Worker static int open_vgem(void)
39*053f45beSAndroid Build Coastguard Worker {
40*053f45beSAndroid Build Coastguard Worker int i, fd;
41*053f45beSAndroid Build Coastguard Worker const char *drmstr = "/dev/dri/card";
42*053f45beSAndroid Build Coastguard Worker
43*053f45beSAndroid Build Coastguard Worker fd = -1;
44*053f45beSAndroid Build Coastguard Worker for (i = 0; i < 16; i++) {
45*053f45beSAndroid Build Coastguard Worker char name[80];
46*053f45beSAndroid Build Coastguard Worker
47*053f45beSAndroid Build Coastguard Worker snprintf(name, 80, "%s%u", drmstr, i);
48*053f45beSAndroid Build Coastguard Worker
49*053f45beSAndroid Build Coastguard Worker fd = open(name, O_RDWR);
50*053f45beSAndroid Build Coastguard Worker if (fd < 0)
51*053f45beSAndroid Build Coastguard Worker continue;
52*053f45beSAndroid Build Coastguard Worker
53*053f45beSAndroid Build Coastguard Worker if (!check_vgem(fd)) {
54*053f45beSAndroid Build Coastguard Worker close(fd);
55*053f45beSAndroid Build Coastguard Worker fd = -1;
56*053f45beSAndroid Build Coastguard Worker continue;
57*053f45beSAndroid Build Coastguard Worker } else {
58*053f45beSAndroid Build Coastguard Worker break;
59*053f45beSAndroid Build Coastguard Worker }
60*053f45beSAndroid Build Coastguard Worker }
61*053f45beSAndroid Build Coastguard Worker return fd;
62*053f45beSAndroid Build Coastguard Worker }
63*053f45beSAndroid Build Coastguard Worker
import_vgem_fd(int vgem_fd,int dma_buf_fd,uint32_t * handle)64*053f45beSAndroid Build Coastguard Worker static int import_vgem_fd(int vgem_fd, int dma_buf_fd, uint32_t *handle)
65*053f45beSAndroid Build Coastguard Worker {
66*053f45beSAndroid Build Coastguard Worker struct drm_prime_handle import_handle = {
67*053f45beSAndroid Build Coastguard Worker .fd = dma_buf_fd,
68*053f45beSAndroid Build Coastguard Worker .flags = 0,
69*053f45beSAndroid Build Coastguard Worker .handle = 0,
70*053f45beSAndroid Build Coastguard Worker };
71*053f45beSAndroid Build Coastguard Worker int ret;
72*053f45beSAndroid Build Coastguard Worker
73*053f45beSAndroid Build Coastguard Worker ret = ioctl(vgem_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &import_handle);
74*053f45beSAndroid Build Coastguard Worker if (ret == 0)
75*053f45beSAndroid Build Coastguard Worker *handle = import_handle.handle;
76*053f45beSAndroid Build Coastguard Worker return ret;
77*053f45beSAndroid Build Coastguard Worker }
78*053f45beSAndroid Build Coastguard Worker
close_handle(int vgem_fd,uint32_t handle)79*053f45beSAndroid Build Coastguard Worker static void close_handle(int vgem_fd, uint32_t handle)
80*053f45beSAndroid Build Coastguard Worker {
81*053f45beSAndroid Build Coastguard Worker struct drm_gem_close close = {
82*053f45beSAndroid Build Coastguard Worker .handle = handle,
83*053f45beSAndroid Build Coastguard Worker };
84*053f45beSAndroid Build Coastguard Worker
85*053f45beSAndroid Build Coastguard Worker ioctl(vgem_fd, DRM_IOCTL_GEM_CLOSE, &close);
86*053f45beSAndroid Build Coastguard Worker }
87*053f45beSAndroid Build Coastguard Worker
dmabuf_heap_open(char * name)88*053f45beSAndroid Build Coastguard Worker static int dmabuf_heap_open(char *name)
89*053f45beSAndroid Build Coastguard Worker {
90*053f45beSAndroid Build Coastguard Worker int ret, fd;
91*053f45beSAndroid Build Coastguard Worker char buf[256];
92*053f45beSAndroid Build Coastguard Worker
93*053f45beSAndroid Build Coastguard Worker ret = snprintf(buf, 256, "%s/%s", DEVPATH, name);
94*053f45beSAndroid Build Coastguard Worker if (ret < 0) {
95*053f45beSAndroid Build Coastguard Worker printf("snprintf failed!\n");
96*053f45beSAndroid Build Coastguard Worker return ret;
97*053f45beSAndroid Build Coastguard Worker }
98*053f45beSAndroid Build Coastguard Worker
99*053f45beSAndroid Build Coastguard Worker fd = open(buf, O_RDWR);
100*053f45beSAndroid Build Coastguard Worker if (fd < 0)
101*053f45beSAndroid Build Coastguard Worker printf("open %s failed!\n", buf);
102*053f45beSAndroid Build Coastguard Worker return fd;
103*053f45beSAndroid Build Coastguard Worker }
104*053f45beSAndroid Build Coastguard Worker
dmabuf_heap_alloc_fdflags(int fd,size_t len,unsigned int fd_flags,unsigned int heap_flags,int * dmabuf_fd)105*053f45beSAndroid Build Coastguard Worker static int dmabuf_heap_alloc_fdflags(int fd, size_t len, unsigned int fd_flags,
106*053f45beSAndroid Build Coastguard Worker unsigned int heap_flags, int *dmabuf_fd)
107*053f45beSAndroid Build Coastguard Worker {
108*053f45beSAndroid Build Coastguard Worker struct dma_heap_allocation_data data = {
109*053f45beSAndroid Build Coastguard Worker .len = len,
110*053f45beSAndroid Build Coastguard Worker .fd = 0,
111*053f45beSAndroid Build Coastguard Worker .fd_flags = fd_flags,
112*053f45beSAndroid Build Coastguard Worker .heap_flags = heap_flags,
113*053f45beSAndroid Build Coastguard Worker };
114*053f45beSAndroid Build Coastguard Worker int ret;
115*053f45beSAndroid Build Coastguard Worker
116*053f45beSAndroid Build Coastguard Worker if (!dmabuf_fd)
117*053f45beSAndroid Build Coastguard Worker return -EINVAL;
118*053f45beSAndroid Build Coastguard Worker
119*053f45beSAndroid Build Coastguard Worker ret = ioctl(fd, DMA_HEAP_IOCTL_ALLOC, &data);
120*053f45beSAndroid Build Coastguard Worker if (ret < 0)
121*053f45beSAndroid Build Coastguard Worker return ret;
122*053f45beSAndroid Build Coastguard Worker *dmabuf_fd = (int)data.fd;
123*053f45beSAndroid Build Coastguard Worker return ret;
124*053f45beSAndroid Build Coastguard Worker }
125*053f45beSAndroid Build Coastguard Worker
dmabuf_heap_alloc(int fd,size_t len,unsigned int flags,int * dmabuf_fd)126*053f45beSAndroid Build Coastguard Worker static int dmabuf_heap_alloc(int fd, size_t len, unsigned int flags,
127*053f45beSAndroid Build Coastguard Worker int *dmabuf_fd)
128*053f45beSAndroid Build Coastguard Worker {
129*053f45beSAndroid Build Coastguard Worker return dmabuf_heap_alloc_fdflags(fd, len, O_RDWR | O_CLOEXEC, flags,
130*053f45beSAndroid Build Coastguard Worker dmabuf_fd);
131*053f45beSAndroid Build Coastguard Worker }
132*053f45beSAndroid Build Coastguard Worker
dmabuf_sync(int fd,int start_stop)133*053f45beSAndroid Build Coastguard Worker static int dmabuf_sync(int fd, int start_stop)
134*053f45beSAndroid Build Coastguard Worker {
135*053f45beSAndroid Build Coastguard Worker struct dma_buf_sync sync = {
136*053f45beSAndroid Build Coastguard Worker .flags = start_stop | DMA_BUF_SYNC_RW,
137*053f45beSAndroid Build Coastguard Worker };
138*053f45beSAndroid Build Coastguard Worker
139*053f45beSAndroid Build Coastguard Worker return ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync);
140*053f45beSAndroid Build Coastguard Worker }
141*053f45beSAndroid Build Coastguard Worker
142*053f45beSAndroid Build Coastguard Worker #define ONE_MEG (1024 * 1024)
143*053f45beSAndroid Build Coastguard Worker
test_alloc_and_import(char * heap_name)144*053f45beSAndroid Build Coastguard Worker static int test_alloc_and_import(char *heap_name)
145*053f45beSAndroid Build Coastguard Worker {
146*053f45beSAndroid Build Coastguard Worker int heap_fd = -1, dmabuf_fd = -1, importer_fd = -1;
147*053f45beSAndroid Build Coastguard Worker uint32_t handle = 0;
148*053f45beSAndroid Build Coastguard Worker void *p = NULL;
149*053f45beSAndroid Build Coastguard Worker int ret;
150*053f45beSAndroid Build Coastguard Worker
151*053f45beSAndroid Build Coastguard Worker heap_fd = dmabuf_heap_open(heap_name);
152*053f45beSAndroid Build Coastguard Worker if (heap_fd < 0)
153*053f45beSAndroid Build Coastguard Worker return -1;
154*053f45beSAndroid Build Coastguard Worker
155*053f45beSAndroid Build Coastguard Worker printf(" Testing allocation and importing: ");
156*053f45beSAndroid Build Coastguard Worker ret = dmabuf_heap_alloc(heap_fd, ONE_MEG, 0, &dmabuf_fd);
157*053f45beSAndroid Build Coastguard Worker if (ret) {
158*053f45beSAndroid Build Coastguard Worker printf("FAIL (Allocation Failed!)\n");
159*053f45beSAndroid Build Coastguard Worker ret = -1;
160*053f45beSAndroid Build Coastguard Worker goto out;
161*053f45beSAndroid Build Coastguard Worker }
162*053f45beSAndroid Build Coastguard Worker /* mmap and write a simple pattern */
163*053f45beSAndroid Build Coastguard Worker p = mmap(NULL,
164*053f45beSAndroid Build Coastguard Worker ONE_MEG,
165*053f45beSAndroid Build Coastguard Worker PROT_READ | PROT_WRITE,
166*053f45beSAndroid Build Coastguard Worker MAP_SHARED,
167*053f45beSAndroid Build Coastguard Worker dmabuf_fd,
168*053f45beSAndroid Build Coastguard Worker 0);
169*053f45beSAndroid Build Coastguard Worker if (p == MAP_FAILED) {
170*053f45beSAndroid Build Coastguard Worker printf("FAIL (mmap() failed)\n");
171*053f45beSAndroid Build Coastguard Worker ret = -1;
172*053f45beSAndroid Build Coastguard Worker goto out;
173*053f45beSAndroid Build Coastguard Worker }
174*053f45beSAndroid Build Coastguard Worker
175*053f45beSAndroid Build Coastguard Worker dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
176*053f45beSAndroid Build Coastguard Worker memset(p, 1, ONE_MEG / 2);
177*053f45beSAndroid Build Coastguard Worker memset((char *)p + ONE_MEG / 2, 0, ONE_MEG / 2);
178*053f45beSAndroid Build Coastguard Worker dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_END);
179*053f45beSAndroid Build Coastguard Worker
180*053f45beSAndroid Build Coastguard Worker importer_fd = open_vgem();
181*053f45beSAndroid Build Coastguard Worker if (importer_fd < 0) {
182*053f45beSAndroid Build Coastguard Worker ret = importer_fd;
183*053f45beSAndroid Build Coastguard Worker printf("(Could not open vgem - skipping): ");
184*053f45beSAndroid Build Coastguard Worker } else {
185*053f45beSAndroid Build Coastguard Worker ret = import_vgem_fd(importer_fd, dmabuf_fd, &handle);
186*053f45beSAndroid Build Coastguard Worker if (ret < 0) {
187*053f45beSAndroid Build Coastguard Worker printf("FAIL (Failed to import buffer)\n");
188*053f45beSAndroid Build Coastguard Worker goto out;
189*053f45beSAndroid Build Coastguard Worker }
190*053f45beSAndroid Build Coastguard Worker }
191*053f45beSAndroid Build Coastguard Worker
192*053f45beSAndroid Build Coastguard Worker ret = dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
193*053f45beSAndroid Build Coastguard Worker if (ret < 0) {
194*053f45beSAndroid Build Coastguard Worker printf("FAIL (DMA_BUF_SYNC_START failed!)\n");
195*053f45beSAndroid Build Coastguard Worker goto out;
196*053f45beSAndroid Build Coastguard Worker }
197*053f45beSAndroid Build Coastguard Worker
198*053f45beSAndroid Build Coastguard Worker memset(p, 0xff, ONE_MEG);
199*053f45beSAndroid Build Coastguard Worker ret = dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_END);
200*053f45beSAndroid Build Coastguard Worker if (ret < 0) {
201*053f45beSAndroid Build Coastguard Worker printf("FAIL (DMA_BUF_SYNC_END failed!)\n");
202*053f45beSAndroid Build Coastguard Worker goto out;
203*053f45beSAndroid Build Coastguard Worker }
204*053f45beSAndroid Build Coastguard Worker
205*053f45beSAndroid Build Coastguard Worker close_handle(importer_fd, handle);
206*053f45beSAndroid Build Coastguard Worker ret = 0;
207*053f45beSAndroid Build Coastguard Worker printf(" OK\n");
208*053f45beSAndroid Build Coastguard Worker out:
209*053f45beSAndroid Build Coastguard Worker if (p)
210*053f45beSAndroid Build Coastguard Worker munmap(p, ONE_MEG);
211*053f45beSAndroid Build Coastguard Worker if (importer_fd >= 0)
212*053f45beSAndroid Build Coastguard Worker close(importer_fd);
213*053f45beSAndroid Build Coastguard Worker if (dmabuf_fd >= 0)
214*053f45beSAndroid Build Coastguard Worker close(dmabuf_fd);
215*053f45beSAndroid Build Coastguard Worker if (heap_fd >= 0)
216*053f45beSAndroid Build Coastguard Worker close(heap_fd);
217*053f45beSAndroid Build Coastguard Worker
218*053f45beSAndroid Build Coastguard Worker return ret;
219*053f45beSAndroid Build Coastguard Worker }
220*053f45beSAndroid Build Coastguard Worker
test_alloc_zeroed(char * heap_name,size_t size)221*053f45beSAndroid Build Coastguard Worker static int test_alloc_zeroed(char *heap_name, size_t size)
222*053f45beSAndroid Build Coastguard Worker {
223*053f45beSAndroid Build Coastguard Worker int heap_fd = -1, dmabuf_fd[32];
224*053f45beSAndroid Build Coastguard Worker int i, j, ret;
225*053f45beSAndroid Build Coastguard Worker void *p = NULL;
226*053f45beSAndroid Build Coastguard Worker char *c;
227*053f45beSAndroid Build Coastguard Worker
228*053f45beSAndroid Build Coastguard Worker printf(" Testing alloced %ldk buffers are zeroed: ", size / 1024);
229*053f45beSAndroid Build Coastguard Worker heap_fd = dmabuf_heap_open(heap_name);
230*053f45beSAndroid Build Coastguard Worker if (heap_fd < 0)
231*053f45beSAndroid Build Coastguard Worker return -1;
232*053f45beSAndroid Build Coastguard Worker
233*053f45beSAndroid Build Coastguard Worker /* Allocate and fill a bunch of buffers */
234*053f45beSAndroid Build Coastguard Worker for (i = 0; i < 32; i++) {
235*053f45beSAndroid Build Coastguard Worker ret = dmabuf_heap_alloc(heap_fd, size, 0, &dmabuf_fd[i]);
236*053f45beSAndroid Build Coastguard Worker if (ret < 0) {
237*053f45beSAndroid Build Coastguard Worker printf("FAIL (Allocation (%i) failed)\n", i);
238*053f45beSAndroid Build Coastguard Worker goto out;
239*053f45beSAndroid Build Coastguard Worker }
240*053f45beSAndroid Build Coastguard Worker /* mmap and fill with simple pattern */
241*053f45beSAndroid Build Coastguard Worker p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd[i], 0);
242*053f45beSAndroid Build Coastguard Worker if (p == MAP_FAILED) {
243*053f45beSAndroid Build Coastguard Worker printf("FAIL (mmap() failed!)\n");
244*053f45beSAndroid Build Coastguard Worker ret = -1;
245*053f45beSAndroid Build Coastguard Worker goto out;
246*053f45beSAndroid Build Coastguard Worker }
247*053f45beSAndroid Build Coastguard Worker dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_START);
248*053f45beSAndroid Build Coastguard Worker memset(p, 0xff, size);
249*053f45beSAndroid Build Coastguard Worker dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_END);
250*053f45beSAndroid Build Coastguard Worker munmap(p, size);
251*053f45beSAndroid Build Coastguard Worker }
252*053f45beSAndroid Build Coastguard Worker /* close them all */
253*053f45beSAndroid Build Coastguard Worker for (i = 0; i < 32; i++)
254*053f45beSAndroid Build Coastguard Worker close(dmabuf_fd[i]);
255*053f45beSAndroid Build Coastguard Worker
256*053f45beSAndroid Build Coastguard Worker /* Allocate and validate all buffers are zeroed */
257*053f45beSAndroid Build Coastguard Worker for (i = 0; i < 32; i++) {
258*053f45beSAndroid Build Coastguard Worker ret = dmabuf_heap_alloc(heap_fd, size, 0, &dmabuf_fd[i]);
259*053f45beSAndroid Build Coastguard Worker if (ret < 0) {
260*053f45beSAndroid Build Coastguard Worker printf("FAIL (Allocation (%i) failed)\n", i);
261*053f45beSAndroid Build Coastguard Worker goto out;
262*053f45beSAndroid Build Coastguard Worker }
263*053f45beSAndroid Build Coastguard Worker
264*053f45beSAndroid Build Coastguard Worker /* mmap and validate everything is zero */
265*053f45beSAndroid Build Coastguard Worker p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd[i], 0);
266*053f45beSAndroid Build Coastguard Worker if (p == MAP_FAILED) {
267*053f45beSAndroid Build Coastguard Worker printf("FAIL (mmap() failed!)\n");
268*053f45beSAndroid Build Coastguard Worker ret = -1;
269*053f45beSAndroid Build Coastguard Worker goto out;
270*053f45beSAndroid Build Coastguard Worker }
271*053f45beSAndroid Build Coastguard Worker dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_START);
272*053f45beSAndroid Build Coastguard Worker c = (char *)p;
273*053f45beSAndroid Build Coastguard Worker for (j = 0; j < size; j++) {
274*053f45beSAndroid Build Coastguard Worker if (c[j] != 0) {
275*053f45beSAndroid Build Coastguard Worker printf("FAIL (Allocated buffer not zeroed @ %i)\n", j);
276*053f45beSAndroid Build Coastguard Worker break;
277*053f45beSAndroid Build Coastguard Worker }
278*053f45beSAndroid Build Coastguard Worker }
279*053f45beSAndroid Build Coastguard Worker dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_END);
280*053f45beSAndroid Build Coastguard Worker munmap(p, size);
281*053f45beSAndroid Build Coastguard Worker }
282*053f45beSAndroid Build Coastguard Worker /* close them all */
283*053f45beSAndroid Build Coastguard Worker for (i = 0; i < 32; i++)
284*053f45beSAndroid Build Coastguard Worker close(dmabuf_fd[i]);
285*053f45beSAndroid Build Coastguard Worker
286*053f45beSAndroid Build Coastguard Worker close(heap_fd);
287*053f45beSAndroid Build Coastguard Worker printf("OK\n");
288*053f45beSAndroid Build Coastguard Worker return 0;
289*053f45beSAndroid Build Coastguard Worker
290*053f45beSAndroid Build Coastguard Worker out:
291*053f45beSAndroid Build Coastguard Worker while (i > 0) {
292*053f45beSAndroid Build Coastguard Worker close(dmabuf_fd[i]);
293*053f45beSAndroid Build Coastguard Worker i--;
294*053f45beSAndroid Build Coastguard Worker }
295*053f45beSAndroid Build Coastguard Worker close(heap_fd);
296*053f45beSAndroid Build Coastguard Worker return ret;
297*053f45beSAndroid Build Coastguard Worker }
298*053f45beSAndroid Build Coastguard Worker
299*053f45beSAndroid Build Coastguard Worker /* Test the ioctl version compatibility w/ a smaller structure then expected */
dmabuf_heap_alloc_older(int fd,size_t len,unsigned int flags,int * dmabuf_fd)300*053f45beSAndroid Build Coastguard Worker static int dmabuf_heap_alloc_older(int fd, size_t len, unsigned int flags,
301*053f45beSAndroid Build Coastguard Worker int *dmabuf_fd)
302*053f45beSAndroid Build Coastguard Worker {
303*053f45beSAndroid Build Coastguard Worker int ret;
304*053f45beSAndroid Build Coastguard Worker unsigned int older_alloc_ioctl;
305*053f45beSAndroid Build Coastguard Worker struct dma_heap_allocation_data_smaller {
306*053f45beSAndroid Build Coastguard Worker __u64 len;
307*053f45beSAndroid Build Coastguard Worker __u32 fd;
308*053f45beSAndroid Build Coastguard Worker __u32 fd_flags;
309*053f45beSAndroid Build Coastguard Worker } data = {
310*053f45beSAndroid Build Coastguard Worker .len = len,
311*053f45beSAndroid Build Coastguard Worker .fd = 0,
312*053f45beSAndroid Build Coastguard Worker .fd_flags = O_RDWR | O_CLOEXEC,
313*053f45beSAndroid Build Coastguard Worker };
314*053f45beSAndroid Build Coastguard Worker
315*053f45beSAndroid Build Coastguard Worker older_alloc_ioctl = _IOWR(DMA_HEAP_IOC_MAGIC, 0x0,
316*053f45beSAndroid Build Coastguard Worker struct dma_heap_allocation_data_smaller);
317*053f45beSAndroid Build Coastguard Worker if (!dmabuf_fd)
318*053f45beSAndroid Build Coastguard Worker return -EINVAL;
319*053f45beSAndroid Build Coastguard Worker
320*053f45beSAndroid Build Coastguard Worker ret = ioctl(fd, older_alloc_ioctl, &data);
321*053f45beSAndroid Build Coastguard Worker if (ret < 0)
322*053f45beSAndroid Build Coastguard Worker return ret;
323*053f45beSAndroid Build Coastguard Worker *dmabuf_fd = (int)data.fd;
324*053f45beSAndroid Build Coastguard Worker return ret;
325*053f45beSAndroid Build Coastguard Worker }
326*053f45beSAndroid Build Coastguard Worker
327*053f45beSAndroid Build Coastguard Worker /* Test the ioctl version compatibility w/ a larger structure then expected */
dmabuf_heap_alloc_newer(int fd,size_t len,unsigned int flags,int * dmabuf_fd)328*053f45beSAndroid Build Coastguard Worker static int dmabuf_heap_alloc_newer(int fd, size_t len, unsigned int flags,
329*053f45beSAndroid Build Coastguard Worker int *dmabuf_fd)
330*053f45beSAndroid Build Coastguard Worker {
331*053f45beSAndroid Build Coastguard Worker int ret;
332*053f45beSAndroid Build Coastguard Worker unsigned int newer_alloc_ioctl;
333*053f45beSAndroid Build Coastguard Worker struct dma_heap_allocation_data_bigger {
334*053f45beSAndroid Build Coastguard Worker __u64 len;
335*053f45beSAndroid Build Coastguard Worker __u32 fd;
336*053f45beSAndroid Build Coastguard Worker __u32 fd_flags;
337*053f45beSAndroid Build Coastguard Worker __u64 heap_flags;
338*053f45beSAndroid Build Coastguard Worker __u64 garbage1;
339*053f45beSAndroid Build Coastguard Worker __u64 garbage2;
340*053f45beSAndroid Build Coastguard Worker __u64 garbage3;
341*053f45beSAndroid Build Coastguard Worker } data = {
342*053f45beSAndroid Build Coastguard Worker .len = len,
343*053f45beSAndroid Build Coastguard Worker .fd = 0,
344*053f45beSAndroid Build Coastguard Worker .fd_flags = O_RDWR | O_CLOEXEC,
345*053f45beSAndroid Build Coastguard Worker .heap_flags = flags,
346*053f45beSAndroid Build Coastguard Worker .garbage1 = 0xffffffff,
347*053f45beSAndroid Build Coastguard Worker .garbage2 = 0x88888888,
348*053f45beSAndroid Build Coastguard Worker .garbage3 = 0x11111111,
349*053f45beSAndroid Build Coastguard Worker };
350*053f45beSAndroid Build Coastguard Worker
351*053f45beSAndroid Build Coastguard Worker newer_alloc_ioctl = _IOWR(DMA_HEAP_IOC_MAGIC, 0x0,
352*053f45beSAndroid Build Coastguard Worker struct dma_heap_allocation_data_bigger);
353*053f45beSAndroid Build Coastguard Worker if (!dmabuf_fd)
354*053f45beSAndroid Build Coastguard Worker return -EINVAL;
355*053f45beSAndroid Build Coastguard Worker
356*053f45beSAndroid Build Coastguard Worker ret = ioctl(fd, newer_alloc_ioctl, &data);
357*053f45beSAndroid Build Coastguard Worker if (ret < 0)
358*053f45beSAndroid Build Coastguard Worker return ret;
359*053f45beSAndroid Build Coastguard Worker
360*053f45beSAndroid Build Coastguard Worker *dmabuf_fd = (int)data.fd;
361*053f45beSAndroid Build Coastguard Worker return ret;
362*053f45beSAndroid Build Coastguard Worker }
363*053f45beSAndroid Build Coastguard Worker
test_alloc_compat(char * heap_name)364*053f45beSAndroid Build Coastguard Worker static int test_alloc_compat(char *heap_name)
365*053f45beSAndroid Build Coastguard Worker {
366*053f45beSAndroid Build Coastguard Worker int heap_fd = -1, dmabuf_fd = -1;
367*053f45beSAndroid Build Coastguard Worker int ret;
368*053f45beSAndroid Build Coastguard Worker
369*053f45beSAndroid Build Coastguard Worker heap_fd = dmabuf_heap_open(heap_name);
370*053f45beSAndroid Build Coastguard Worker if (heap_fd < 0)
371*053f45beSAndroid Build Coastguard Worker return -1;
372*053f45beSAndroid Build Coastguard Worker
373*053f45beSAndroid Build Coastguard Worker printf(" Testing (theoretical)older alloc compat: ");
374*053f45beSAndroid Build Coastguard Worker ret = dmabuf_heap_alloc_older(heap_fd, ONE_MEG, 0, &dmabuf_fd);
375*053f45beSAndroid Build Coastguard Worker if (ret) {
376*053f45beSAndroid Build Coastguard Worker printf("FAIL (Older compat allocation failed!)\n");
377*053f45beSAndroid Build Coastguard Worker ret = -1;
378*053f45beSAndroid Build Coastguard Worker goto out;
379*053f45beSAndroid Build Coastguard Worker }
380*053f45beSAndroid Build Coastguard Worker close(dmabuf_fd);
381*053f45beSAndroid Build Coastguard Worker printf("OK\n");
382*053f45beSAndroid Build Coastguard Worker
383*053f45beSAndroid Build Coastguard Worker printf(" Testing (theoretical)newer alloc compat: ");
384*053f45beSAndroid Build Coastguard Worker ret = dmabuf_heap_alloc_newer(heap_fd, ONE_MEG, 0, &dmabuf_fd);
385*053f45beSAndroid Build Coastguard Worker if (ret) {
386*053f45beSAndroid Build Coastguard Worker printf("FAIL (Newer compat allocation failed!)\n");
387*053f45beSAndroid Build Coastguard Worker ret = -1;
388*053f45beSAndroid Build Coastguard Worker goto out;
389*053f45beSAndroid Build Coastguard Worker }
390*053f45beSAndroid Build Coastguard Worker printf("OK\n");
391*053f45beSAndroid Build Coastguard Worker out:
392*053f45beSAndroid Build Coastguard Worker if (dmabuf_fd >= 0)
393*053f45beSAndroid Build Coastguard Worker close(dmabuf_fd);
394*053f45beSAndroid Build Coastguard Worker if (heap_fd >= 0)
395*053f45beSAndroid Build Coastguard Worker close(heap_fd);
396*053f45beSAndroid Build Coastguard Worker
397*053f45beSAndroid Build Coastguard Worker return ret;
398*053f45beSAndroid Build Coastguard Worker }
399*053f45beSAndroid Build Coastguard Worker
test_alloc_errors(char * heap_name)400*053f45beSAndroid Build Coastguard Worker static int test_alloc_errors(char *heap_name)
401*053f45beSAndroid Build Coastguard Worker {
402*053f45beSAndroid Build Coastguard Worker int heap_fd = -1, dmabuf_fd = -1;
403*053f45beSAndroid Build Coastguard Worker int ret;
404*053f45beSAndroid Build Coastguard Worker
405*053f45beSAndroid Build Coastguard Worker heap_fd = dmabuf_heap_open(heap_name);
406*053f45beSAndroid Build Coastguard Worker if (heap_fd < 0)
407*053f45beSAndroid Build Coastguard Worker return -1;
408*053f45beSAndroid Build Coastguard Worker
409*053f45beSAndroid Build Coastguard Worker printf(" Testing expected error cases: ");
410*053f45beSAndroid Build Coastguard Worker ret = dmabuf_heap_alloc(0, ONE_MEG, 0x111111, &dmabuf_fd);
411*053f45beSAndroid Build Coastguard Worker if (!ret) {
412*053f45beSAndroid Build Coastguard Worker printf("FAIL (Did not see expected error (invalid fd)!)\n");
413*053f45beSAndroid Build Coastguard Worker ret = -1;
414*053f45beSAndroid Build Coastguard Worker goto out;
415*053f45beSAndroid Build Coastguard Worker }
416*053f45beSAndroid Build Coastguard Worker
417*053f45beSAndroid Build Coastguard Worker ret = dmabuf_heap_alloc(heap_fd, ONE_MEG, 0x111111, &dmabuf_fd);
418*053f45beSAndroid Build Coastguard Worker if (!ret) {
419*053f45beSAndroid Build Coastguard Worker printf("FAIL (Did not see expected error (invalid heap flags)!)\n");
420*053f45beSAndroid Build Coastguard Worker ret = -1;
421*053f45beSAndroid Build Coastguard Worker goto out;
422*053f45beSAndroid Build Coastguard Worker }
423*053f45beSAndroid Build Coastguard Worker
424*053f45beSAndroid Build Coastguard Worker ret = dmabuf_heap_alloc_fdflags(heap_fd, ONE_MEG,
425*053f45beSAndroid Build Coastguard Worker ~(O_RDWR | O_CLOEXEC), 0, &dmabuf_fd);
426*053f45beSAndroid Build Coastguard Worker if (!ret) {
427*053f45beSAndroid Build Coastguard Worker printf("FAIL (Did not see expected error (invalid fd flags)!)\n");
428*053f45beSAndroid Build Coastguard Worker ret = -1;
429*053f45beSAndroid Build Coastguard Worker goto out;
430*053f45beSAndroid Build Coastguard Worker }
431*053f45beSAndroid Build Coastguard Worker
432*053f45beSAndroid Build Coastguard Worker printf("OK\n");
433*053f45beSAndroid Build Coastguard Worker ret = 0;
434*053f45beSAndroid Build Coastguard Worker out:
435*053f45beSAndroid Build Coastguard Worker if (dmabuf_fd >= 0)
436*053f45beSAndroid Build Coastguard Worker close(dmabuf_fd);
437*053f45beSAndroid Build Coastguard Worker if (heap_fd >= 0)
438*053f45beSAndroid Build Coastguard Worker close(heap_fd);
439*053f45beSAndroid Build Coastguard Worker
440*053f45beSAndroid Build Coastguard Worker return ret;
441*053f45beSAndroid Build Coastguard Worker }
442*053f45beSAndroid Build Coastguard Worker
main(void)443*053f45beSAndroid Build Coastguard Worker int main(void)
444*053f45beSAndroid Build Coastguard Worker {
445*053f45beSAndroid Build Coastguard Worker DIR *d;
446*053f45beSAndroid Build Coastguard Worker struct dirent *dir;
447*053f45beSAndroid Build Coastguard Worker int ret = -1;
448*053f45beSAndroid Build Coastguard Worker
449*053f45beSAndroid Build Coastguard Worker d = opendir(DEVPATH);
450*053f45beSAndroid Build Coastguard Worker if (!d) {
451*053f45beSAndroid Build Coastguard Worker printf("No %s directory?\n", DEVPATH);
452*053f45beSAndroid Build Coastguard Worker return -1;
453*053f45beSAndroid Build Coastguard Worker }
454*053f45beSAndroid Build Coastguard Worker
455*053f45beSAndroid Build Coastguard Worker while ((dir = readdir(d)) != NULL) {
456*053f45beSAndroid Build Coastguard Worker if (!strncmp(dir->d_name, ".", 2))
457*053f45beSAndroid Build Coastguard Worker continue;
458*053f45beSAndroid Build Coastguard Worker if (!strncmp(dir->d_name, "..", 3))
459*053f45beSAndroid Build Coastguard Worker continue;
460*053f45beSAndroid Build Coastguard Worker
461*053f45beSAndroid Build Coastguard Worker printf("Testing heap: %s\n", dir->d_name);
462*053f45beSAndroid Build Coastguard Worker printf("=======================================\n");
463*053f45beSAndroid Build Coastguard Worker ret = test_alloc_and_import(dir->d_name);
464*053f45beSAndroid Build Coastguard Worker if (ret)
465*053f45beSAndroid Build Coastguard Worker break;
466*053f45beSAndroid Build Coastguard Worker
467*053f45beSAndroid Build Coastguard Worker ret = test_alloc_zeroed(dir->d_name, 4 * 1024);
468*053f45beSAndroid Build Coastguard Worker if (ret)
469*053f45beSAndroid Build Coastguard Worker break;
470*053f45beSAndroid Build Coastguard Worker
471*053f45beSAndroid Build Coastguard Worker ret = test_alloc_zeroed(dir->d_name, ONE_MEG);
472*053f45beSAndroid Build Coastguard Worker if (ret)
473*053f45beSAndroid Build Coastguard Worker break;
474*053f45beSAndroid Build Coastguard Worker
475*053f45beSAndroid Build Coastguard Worker ret = test_alloc_compat(dir->d_name);
476*053f45beSAndroid Build Coastguard Worker if (ret)
477*053f45beSAndroid Build Coastguard Worker break;
478*053f45beSAndroid Build Coastguard Worker
479*053f45beSAndroid Build Coastguard Worker ret = test_alloc_errors(dir->d_name);
480*053f45beSAndroid Build Coastguard Worker if (ret)
481*053f45beSAndroid Build Coastguard Worker break;
482*053f45beSAndroid Build Coastguard Worker }
483*053f45beSAndroid Build Coastguard Worker closedir(d);
484*053f45beSAndroid Build Coastguard Worker
485*053f45beSAndroid Build Coastguard Worker return ret;
486*053f45beSAndroid Build Coastguard Worker }
487