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