162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#include <dirent.h>
462306a36Sopenharmony_ci#include <errno.h>
562306a36Sopenharmony_ci#include <fcntl.h>
662306a36Sopenharmony_ci#include <stdio.h>
762306a36Sopenharmony_ci#include <stdlib.h>
862306a36Sopenharmony_ci#include <stdint.h>
962306a36Sopenharmony_ci#include <string.h>
1062306a36Sopenharmony_ci#include <unistd.h>
1162306a36Sopenharmony_ci#include <sys/ioctl.h>
1262306a36Sopenharmony_ci#include <sys/mman.h>
1362306a36Sopenharmony_ci#include <sys/types.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/dma-buf.h>
1662306a36Sopenharmony_ci#include <linux/dma-heap.h>
1762306a36Sopenharmony_ci#include <drm/drm.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#define DEVPATH "/dev/dma_heap"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistatic int check_vgem(int fd)
2262306a36Sopenharmony_ci{
2362306a36Sopenharmony_ci	drm_version_t version = { 0 };
2462306a36Sopenharmony_ci	char name[5];
2562306a36Sopenharmony_ci	int ret;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	version.name_len = 4;
2862306a36Sopenharmony_ci	version.name = name;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	ret = ioctl(fd, DRM_IOCTL_VERSION, &version);
3162306a36Sopenharmony_ci	if (ret)
3262306a36Sopenharmony_ci		return 0;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	return !strcmp(name, "vgem");
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic int open_vgem(void)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	int i, fd;
4062306a36Sopenharmony_ci	const char *drmstr = "/dev/dri/card";
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	fd = -1;
4362306a36Sopenharmony_ci	for (i = 0; i < 16; i++) {
4462306a36Sopenharmony_ci		char name[80];
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci		snprintf(name, 80, "%s%u", drmstr, i);
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci		fd = open(name, O_RDWR);
4962306a36Sopenharmony_ci		if (fd < 0)
5062306a36Sopenharmony_ci			continue;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci		if (!check_vgem(fd)) {
5362306a36Sopenharmony_ci			close(fd);
5462306a36Sopenharmony_ci			fd = -1;
5562306a36Sopenharmony_ci			continue;
5662306a36Sopenharmony_ci		} else {
5762306a36Sopenharmony_ci			break;
5862306a36Sopenharmony_ci		}
5962306a36Sopenharmony_ci	}
6062306a36Sopenharmony_ci	return fd;
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic int import_vgem_fd(int vgem_fd, int dma_buf_fd, uint32_t *handle)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	struct drm_prime_handle import_handle = {
6662306a36Sopenharmony_ci		.fd = dma_buf_fd,
6762306a36Sopenharmony_ci		.flags = 0,
6862306a36Sopenharmony_ci		.handle = 0,
6962306a36Sopenharmony_ci	 };
7062306a36Sopenharmony_ci	int ret;
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	ret = ioctl(vgem_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &import_handle);
7362306a36Sopenharmony_ci	if (ret == 0)
7462306a36Sopenharmony_ci		*handle = import_handle.handle;
7562306a36Sopenharmony_ci	return ret;
7662306a36Sopenharmony_ci}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cistatic void close_handle(int vgem_fd, uint32_t handle)
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci	struct drm_gem_close close = {
8162306a36Sopenharmony_ci		.handle = handle,
8262306a36Sopenharmony_ci	};
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	ioctl(vgem_fd, DRM_IOCTL_GEM_CLOSE, &close);
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cistatic int dmabuf_heap_open(char *name)
8862306a36Sopenharmony_ci{
8962306a36Sopenharmony_ci	int ret, fd;
9062306a36Sopenharmony_ci	char buf[256];
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	ret = snprintf(buf, 256, "%s/%s", DEVPATH, name);
9362306a36Sopenharmony_ci	if (ret < 0) {
9462306a36Sopenharmony_ci		printf("snprintf failed!\n");
9562306a36Sopenharmony_ci		return ret;
9662306a36Sopenharmony_ci	}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	fd = open(buf, O_RDWR);
9962306a36Sopenharmony_ci	if (fd < 0)
10062306a36Sopenharmony_ci		printf("open %s failed!\n", buf);
10162306a36Sopenharmony_ci	return fd;
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistatic int dmabuf_heap_alloc_fdflags(int fd, size_t len, unsigned int fd_flags,
10562306a36Sopenharmony_ci				     unsigned int heap_flags, int *dmabuf_fd)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	struct dma_heap_allocation_data data = {
10862306a36Sopenharmony_ci		.len = len,
10962306a36Sopenharmony_ci		.fd = 0,
11062306a36Sopenharmony_ci		.fd_flags = fd_flags,
11162306a36Sopenharmony_ci		.heap_flags = heap_flags,
11262306a36Sopenharmony_ci	};
11362306a36Sopenharmony_ci	int ret;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	if (!dmabuf_fd)
11662306a36Sopenharmony_ci		return -EINVAL;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	ret = ioctl(fd, DMA_HEAP_IOCTL_ALLOC, &data);
11962306a36Sopenharmony_ci	if (ret < 0)
12062306a36Sopenharmony_ci		return ret;
12162306a36Sopenharmony_ci	*dmabuf_fd = (int)data.fd;
12262306a36Sopenharmony_ci	return ret;
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistatic int dmabuf_heap_alloc(int fd, size_t len, unsigned int flags,
12662306a36Sopenharmony_ci			     int *dmabuf_fd)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	return dmabuf_heap_alloc_fdflags(fd, len, O_RDWR | O_CLOEXEC, flags,
12962306a36Sopenharmony_ci					 dmabuf_fd);
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cistatic int dmabuf_sync(int fd, int start_stop)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	struct dma_buf_sync sync = {
13562306a36Sopenharmony_ci		.flags = start_stop | DMA_BUF_SYNC_RW,
13662306a36Sopenharmony_ci	};
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	return ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync);
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci#define ONE_MEG (1024 * 1024)
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_cistatic int test_alloc_and_import(char *heap_name)
14462306a36Sopenharmony_ci{
14562306a36Sopenharmony_ci	int heap_fd = -1, dmabuf_fd = -1, importer_fd = -1;
14662306a36Sopenharmony_ci	uint32_t handle = 0;
14762306a36Sopenharmony_ci	void *p = NULL;
14862306a36Sopenharmony_ci	int ret;
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	heap_fd = dmabuf_heap_open(heap_name);
15162306a36Sopenharmony_ci	if (heap_fd < 0)
15262306a36Sopenharmony_ci		return -1;
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	printf("  Testing allocation and importing:  ");
15562306a36Sopenharmony_ci	ret = dmabuf_heap_alloc(heap_fd, ONE_MEG, 0, &dmabuf_fd);
15662306a36Sopenharmony_ci	if (ret) {
15762306a36Sopenharmony_ci		printf("FAIL (Allocation Failed!)\n");
15862306a36Sopenharmony_ci		ret = -1;
15962306a36Sopenharmony_ci		goto out;
16062306a36Sopenharmony_ci	}
16162306a36Sopenharmony_ci	/* mmap and write a simple pattern */
16262306a36Sopenharmony_ci	p = mmap(NULL,
16362306a36Sopenharmony_ci		 ONE_MEG,
16462306a36Sopenharmony_ci		 PROT_READ | PROT_WRITE,
16562306a36Sopenharmony_ci		 MAP_SHARED,
16662306a36Sopenharmony_ci		 dmabuf_fd,
16762306a36Sopenharmony_ci		 0);
16862306a36Sopenharmony_ci	if (p == MAP_FAILED) {
16962306a36Sopenharmony_ci		printf("FAIL (mmap() failed)\n");
17062306a36Sopenharmony_ci		ret = -1;
17162306a36Sopenharmony_ci		goto out;
17262306a36Sopenharmony_ci	}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
17562306a36Sopenharmony_ci	memset(p, 1, ONE_MEG / 2);
17662306a36Sopenharmony_ci	memset((char *)p + ONE_MEG / 2, 0, ONE_MEG / 2);
17762306a36Sopenharmony_ci	dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_END);
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	importer_fd = open_vgem();
18062306a36Sopenharmony_ci	if (importer_fd < 0) {
18162306a36Sopenharmony_ci		ret = importer_fd;
18262306a36Sopenharmony_ci		printf("(Could not open vgem - skipping):  ");
18362306a36Sopenharmony_ci	} else {
18462306a36Sopenharmony_ci		ret = import_vgem_fd(importer_fd, dmabuf_fd, &handle);
18562306a36Sopenharmony_ci		if (ret < 0) {
18662306a36Sopenharmony_ci			printf("FAIL (Failed to import buffer)\n");
18762306a36Sopenharmony_ci			goto out;
18862306a36Sopenharmony_ci		}
18962306a36Sopenharmony_ci	}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	ret = dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_START);
19262306a36Sopenharmony_ci	if (ret < 0) {
19362306a36Sopenharmony_ci		printf("FAIL (DMA_BUF_SYNC_START failed!)\n");
19462306a36Sopenharmony_ci		goto out;
19562306a36Sopenharmony_ci	}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	memset(p, 0xff, ONE_MEG);
19862306a36Sopenharmony_ci	ret = dmabuf_sync(dmabuf_fd, DMA_BUF_SYNC_END);
19962306a36Sopenharmony_ci	if (ret < 0) {
20062306a36Sopenharmony_ci		printf("FAIL (DMA_BUF_SYNC_END failed!)\n");
20162306a36Sopenharmony_ci		goto out;
20262306a36Sopenharmony_ci	}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	close_handle(importer_fd, handle);
20562306a36Sopenharmony_ci	ret = 0;
20662306a36Sopenharmony_ci	printf(" OK\n");
20762306a36Sopenharmony_ciout:
20862306a36Sopenharmony_ci	if (p)
20962306a36Sopenharmony_ci		munmap(p, ONE_MEG);
21062306a36Sopenharmony_ci	if (importer_fd >= 0)
21162306a36Sopenharmony_ci		close(importer_fd);
21262306a36Sopenharmony_ci	if (dmabuf_fd >= 0)
21362306a36Sopenharmony_ci		close(dmabuf_fd);
21462306a36Sopenharmony_ci	if (heap_fd >= 0)
21562306a36Sopenharmony_ci		close(heap_fd);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	return ret;
21862306a36Sopenharmony_ci}
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_cistatic int test_alloc_zeroed(char *heap_name, size_t size)
22162306a36Sopenharmony_ci{
22262306a36Sopenharmony_ci	int heap_fd = -1, dmabuf_fd[32];
22362306a36Sopenharmony_ci	int i, j, ret;
22462306a36Sopenharmony_ci	void *p = NULL;
22562306a36Sopenharmony_ci	char *c;
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	printf("  Testing alloced %ldk buffers are zeroed:  ", size / 1024);
22862306a36Sopenharmony_ci	heap_fd = dmabuf_heap_open(heap_name);
22962306a36Sopenharmony_ci	if (heap_fd < 0)
23062306a36Sopenharmony_ci		return -1;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	/* Allocate and fill a bunch of buffers */
23362306a36Sopenharmony_ci	for (i = 0; i < 32; i++) {
23462306a36Sopenharmony_ci		ret = dmabuf_heap_alloc(heap_fd, size, 0, &dmabuf_fd[i]);
23562306a36Sopenharmony_ci		if (ret < 0) {
23662306a36Sopenharmony_ci			printf("FAIL (Allocation (%i) failed)\n", i);
23762306a36Sopenharmony_ci			goto out;
23862306a36Sopenharmony_ci		}
23962306a36Sopenharmony_ci		/* mmap and fill with simple pattern */
24062306a36Sopenharmony_ci		p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd[i], 0);
24162306a36Sopenharmony_ci		if (p == MAP_FAILED) {
24262306a36Sopenharmony_ci			printf("FAIL (mmap() failed!)\n");
24362306a36Sopenharmony_ci			ret = -1;
24462306a36Sopenharmony_ci			goto out;
24562306a36Sopenharmony_ci		}
24662306a36Sopenharmony_ci		dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_START);
24762306a36Sopenharmony_ci		memset(p, 0xff, size);
24862306a36Sopenharmony_ci		dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_END);
24962306a36Sopenharmony_ci		munmap(p, size);
25062306a36Sopenharmony_ci	}
25162306a36Sopenharmony_ci	/* close them all */
25262306a36Sopenharmony_ci	for (i = 0; i < 32; i++)
25362306a36Sopenharmony_ci		close(dmabuf_fd[i]);
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	/* Allocate and validate all buffers are zeroed */
25662306a36Sopenharmony_ci	for (i = 0; i < 32; i++) {
25762306a36Sopenharmony_ci		ret = dmabuf_heap_alloc(heap_fd, size, 0, &dmabuf_fd[i]);
25862306a36Sopenharmony_ci		if (ret < 0) {
25962306a36Sopenharmony_ci			printf("FAIL (Allocation (%i) failed)\n", i);
26062306a36Sopenharmony_ci			goto out;
26162306a36Sopenharmony_ci		}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci		/* mmap and validate everything is zero */
26462306a36Sopenharmony_ci		p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd[i], 0);
26562306a36Sopenharmony_ci		if (p == MAP_FAILED) {
26662306a36Sopenharmony_ci			printf("FAIL (mmap() failed!)\n");
26762306a36Sopenharmony_ci			ret = -1;
26862306a36Sopenharmony_ci			goto out;
26962306a36Sopenharmony_ci		}
27062306a36Sopenharmony_ci		dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_START);
27162306a36Sopenharmony_ci		c = (char *)p;
27262306a36Sopenharmony_ci		for (j = 0; j < size; j++) {
27362306a36Sopenharmony_ci			if (c[j] != 0) {
27462306a36Sopenharmony_ci				printf("FAIL (Allocated buffer not zeroed @ %i)\n", j);
27562306a36Sopenharmony_ci				break;
27662306a36Sopenharmony_ci			}
27762306a36Sopenharmony_ci		}
27862306a36Sopenharmony_ci		dmabuf_sync(dmabuf_fd[i], DMA_BUF_SYNC_END);
27962306a36Sopenharmony_ci		munmap(p, size);
28062306a36Sopenharmony_ci	}
28162306a36Sopenharmony_ci	/* close them all */
28262306a36Sopenharmony_ci	for (i = 0; i < 32; i++)
28362306a36Sopenharmony_ci		close(dmabuf_fd[i]);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	close(heap_fd);
28662306a36Sopenharmony_ci	printf("OK\n");
28762306a36Sopenharmony_ci	return 0;
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ciout:
29062306a36Sopenharmony_ci	while (i > 0) {
29162306a36Sopenharmony_ci		close(dmabuf_fd[i]);
29262306a36Sopenharmony_ci		i--;
29362306a36Sopenharmony_ci	}
29462306a36Sopenharmony_ci	close(heap_fd);
29562306a36Sopenharmony_ci	return ret;
29662306a36Sopenharmony_ci}
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci/* Test the ioctl version compatibility w/ a smaller structure then expected */
29962306a36Sopenharmony_cistatic int dmabuf_heap_alloc_older(int fd, size_t len, unsigned int flags,
30062306a36Sopenharmony_ci				   int *dmabuf_fd)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	int ret;
30362306a36Sopenharmony_ci	unsigned int older_alloc_ioctl;
30462306a36Sopenharmony_ci	struct dma_heap_allocation_data_smaller {
30562306a36Sopenharmony_ci		__u64 len;
30662306a36Sopenharmony_ci		__u32 fd;
30762306a36Sopenharmony_ci		__u32 fd_flags;
30862306a36Sopenharmony_ci	} data = {
30962306a36Sopenharmony_ci		.len = len,
31062306a36Sopenharmony_ci		.fd = 0,
31162306a36Sopenharmony_ci		.fd_flags = O_RDWR | O_CLOEXEC,
31262306a36Sopenharmony_ci	};
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	older_alloc_ioctl = _IOWR(DMA_HEAP_IOC_MAGIC, 0x0,
31562306a36Sopenharmony_ci				  struct dma_heap_allocation_data_smaller);
31662306a36Sopenharmony_ci	if (!dmabuf_fd)
31762306a36Sopenharmony_ci		return -EINVAL;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	ret = ioctl(fd, older_alloc_ioctl, &data);
32062306a36Sopenharmony_ci	if (ret < 0)
32162306a36Sopenharmony_ci		return ret;
32262306a36Sopenharmony_ci	*dmabuf_fd = (int)data.fd;
32362306a36Sopenharmony_ci	return ret;
32462306a36Sopenharmony_ci}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci/* Test the ioctl version compatibility w/ a larger structure then expected */
32762306a36Sopenharmony_cistatic int dmabuf_heap_alloc_newer(int fd, size_t len, unsigned int flags,
32862306a36Sopenharmony_ci				   int *dmabuf_fd)
32962306a36Sopenharmony_ci{
33062306a36Sopenharmony_ci	int ret;
33162306a36Sopenharmony_ci	unsigned int newer_alloc_ioctl;
33262306a36Sopenharmony_ci	struct dma_heap_allocation_data_bigger {
33362306a36Sopenharmony_ci		__u64 len;
33462306a36Sopenharmony_ci		__u32 fd;
33562306a36Sopenharmony_ci		__u32 fd_flags;
33662306a36Sopenharmony_ci		__u64 heap_flags;
33762306a36Sopenharmony_ci		__u64 garbage1;
33862306a36Sopenharmony_ci		__u64 garbage2;
33962306a36Sopenharmony_ci		__u64 garbage3;
34062306a36Sopenharmony_ci	} data = {
34162306a36Sopenharmony_ci		.len = len,
34262306a36Sopenharmony_ci		.fd = 0,
34362306a36Sopenharmony_ci		.fd_flags = O_RDWR | O_CLOEXEC,
34462306a36Sopenharmony_ci		.heap_flags = flags,
34562306a36Sopenharmony_ci		.garbage1 = 0xffffffff,
34662306a36Sopenharmony_ci		.garbage2 = 0x88888888,
34762306a36Sopenharmony_ci		.garbage3 = 0x11111111,
34862306a36Sopenharmony_ci	};
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	newer_alloc_ioctl = _IOWR(DMA_HEAP_IOC_MAGIC, 0x0,
35162306a36Sopenharmony_ci				  struct dma_heap_allocation_data_bigger);
35262306a36Sopenharmony_ci	if (!dmabuf_fd)
35362306a36Sopenharmony_ci		return -EINVAL;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	ret = ioctl(fd, newer_alloc_ioctl, &data);
35662306a36Sopenharmony_ci	if (ret < 0)
35762306a36Sopenharmony_ci		return ret;
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	*dmabuf_fd = (int)data.fd;
36062306a36Sopenharmony_ci	return ret;
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_cistatic int test_alloc_compat(char *heap_name)
36462306a36Sopenharmony_ci{
36562306a36Sopenharmony_ci	int heap_fd = -1, dmabuf_fd = -1;
36662306a36Sopenharmony_ci	int ret;
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	heap_fd = dmabuf_heap_open(heap_name);
36962306a36Sopenharmony_ci	if (heap_fd < 0)
37062306a36Sopenharmony_ci		return -1;
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	printf("  Testing (theoretical)older alloc compat:  ");
37362306a36Sopenharmony_ci	ret = dmabuf_heap_alloc_older(heap_fd, ONE_MEG, 0, &dmabuf_fd);
37462306a36Sopenharmony_ci	if (ret) {
37562306a36Sopenharmony_ci		printf("FAIL (Older compat allocation failed!)\n");
37662306a36Sopenharmony_ci		ret = -1;
37762306a36Sopenharmony_ci		goto out;
37862306a36Sopenharmony_ci	}
37962306a36Sopenharmony_ci	close(dmabuf_fd);
38062306a36Sopenharmony_ci	printf("OK\n");
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	printf("  Testing (theoretical)newer alloc compat:  ");
38362306a36Sopenharmony_ci	ret = dmabuf_heap_alloc_newer(heap_fd, ONE_MEG, 0, &dmabuf_fd);
38462306a36Sopenharmony_ci	if (ret) {
38562306a36Sopenharmony_ci		printf("FAIL (Newer compat allocation failed!)\n");
38662306a36Sopenharmony_ci		ret = -1;
38762306a36Sopenharmony_ci		goto out;
38862306a36Sopenharmony_ci	}
38962306a36Sopenharmony_ci	printf("OK\n");
39062306a36Sopenharmony_ciout:
39162306a36Sopenharmony_ci	if (dmabuf_fd >= 0)
39262306a36Sopenharmony_ci		close(dmabuf_fd);
39362306a36Sopenharmony_ci	if (heap_fd >= 0)
39462306a36Sopenharmony_ci		close(heap_fd);
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	return ret;
39762306a36Sopenharmony_ci}
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_cistatic int test_alloc_errors(char *heap_name)
40062306a36Sopenharmony_ci{
40162306a36Sopenharmony_ci	int heap_fd = -1, dmabuf_fd = -1;
40262306a36Sopenharmony_ci	int ret;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	heap_fd = dmabuf_heap_open(heap_name);
40562306a36Sopenharmony_ci	if (heap_fd < 0)
40662306a36Sopenharmony_ci		return -1;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	printf("  Testing expected error cases:  ");
40962306a36Sopenharmony_ci	ret = dmabuf_heap_alloc(0, ONE_MEG, 0x111111, &dmabuf_fd);
41062306a36Sopenharmony_ci	if (!ret) {
41162306a36Sopenharmony_ci		printf("FAIL (Did not see expected error (invalid fd)!)\n");
41262306a36Sopenharmony_ci		ret = -1;
41362306a36Sopenharmony_ci		goto out;
41462306a36Sopenharmony_ci	}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	ret = dmabuf_heap_alloc(heap_fd, ONE_MEG, 0x111111, &dmabuf_fd);
41762306a36Sopenharmony_ci	if (!ret) {
41862306a36Sopenharmony_ci		printf("FAIL (Did not see expected error (invalid heap flags)!)\n");
41962306a36Sopenharmony_ci		ret = -1;
42062306a36Sopenharmony_ci		goto out;
42162306a36Sopenharmony_ci	}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	ret = dmabuf_heap_alloc_fdflags(heap_fd, ONE_MEG,
42462306a36Sopenharmony_ci					~(O_RDWR | O_CLOEXEC), 0, &dmabuf_fd);
42562306a36Sopenharmony_ci	if (!ret) {
42662306a36Sopenharmony_ci		printf("FAIL (Did not see expected error (invalid fd flags)!)\n");
42762306a36Sopenharmony_ci		ret = -1;
42862306a36Sopenharmony_ci		goto out;
42962306a36Sopenharmony_ci	}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	printf("OK\n");
43262306a36Sopenharmony_ci	ret = 0;
43362306a36Sopenharmony_ciout:
43462306a36Sopenharmony_ci	if (dmabuf_fd >= 0)
43562306a36Sopenharmony_ci		close(dmabuf_fd);
43662306a36Sopenharmony_ci	if (heap_fd >= 0)
43762306a36Sopenharmony_ci		close(heap_fd);
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	return ret;
44062306a36Sopenharmony_ci}
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ciint main(void)
44362306a36Sopenharmony_ci{
44462306a36Sopenharmony_ci	DIR *d;
44562306a36Sopenharmony_ci	struct dirent *dir;
44662306a36Sopenharmony_ci	int ret = -1;
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	d = opendir(DEVPATH);
44962306a36Sopenharmony_ci	if (!d) {
45062306a36Sopenharmony_ci		printf("No %s directory?\n", DEVPATH);
45162306a36Sopenharmony_ci		return -1;
45262306a36Sopenharmony_ci	}
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	while ((dir = readdir(d)) != NULL) {
45562306a36Sopenharmony_ci		if (!strncmp(dir->d_name, ".", 2))
45662306a36Sopenharmony_ci			continue;
45762306a36Sopenharmony_ci		if (!strncmp(dir->d_name, "..", 3))
45862306a36Sopenharmony_ci			continue;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci		printf("Testing heap: %s\n", dir->d_name);
46162306a36Sopenharmony_ci		printf("=======================================\n");
46262306a36Sopenharmony_ci		ret = test_alloc_and_import(dir->d_name);
46362306a36Sopenharmony_ci		if (ret)
46462306a36Sopenharmony_ci			break;
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci		ret = test_alloc_zeroed(dir->d_name, 4 * 1024);
46762306a36Sopenharmony_ci		if (ret)
46862306a36Sopenharmony_ci			break;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci		ret = test_alloc_zeroed(dir->d_name, ONE_MEG);
47162306a36Sopenharmony_ci		if (ret)
47262306a36Sopenharmony_ci			break;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci		ret = test_alloc_compat(dir->d_name);
47562306a36Sopenharmony_ci		if (ret)
47662306a36Sopenharmony_ci			break;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci		ret = test_alloc_errors(dir->d_name);
47962306a36Sopenharmony_ci		if (ret)
48062306a36Sopenharmony_ci			break;
48162306a36Sopenharmony_ci	}
48262306a36Sopenharmony_ci	closedir(d);
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	return ret;
48562306a36Sopenharmony_ci}
486