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