blob: 7532a6e123a3e7aae52fd25ded899c7aca0a053f [file] [edit]
// SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB
/*
* Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*
* DMA-buf heap allocator implementation
*/
#include "config.h"
#include <errno.h>
#include <infiniband/dmabuf_heap.h>
#if HAVE_LINUX_DMA_HEAP_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/dma-heap.h>
#include <util/util.h>
struct ibv_dmabuf_heap {
int heap_fd;
};
static struct ibv_dmabuf_heap *ibv_dmabuf_heap_init(const char *heap_name)
{
struct ibv_dmabuf_heap *heap;
char path[256];
int fd;
if (!heap_name) {
errno = EINVAL;
return NULL;
}
if (!check_snprintf(path, sizeof(path), "/dev/dma_heap/%s", heap_name)) {
errno = ENOMEM;
return NULL;
}
fd = open(path, O_RDWR | O_CLOEXEC);
if (fd < 0)
return NULL;
heap = calloc(1, sizeof(*heap));
if (!heap) {
close(fd);
errno = ENOMEM;
return NULL;
}
heap->heap_fd = fd;
return heap;
}
struct ibv_dmabuf_heap *ibv_dmabuf_heap_cc_shared_init(void)
{
return ibv_dmabuf_heap_init("system_cc_shared");
}
void ibv_dmabuf_heap_destroy(struct ibv_dmabuf_heap *heap)
{
close(heap->heap_fd);
free(heap);
}
void *ibv_dmabuf_heap_alloc(struct ibv_dmabuf_heap *heap, size_t size,
int *dmabuf_fd)
{
struct dma_heap_allocation_data heap_data = {};
void *buf;
int fd;
heap_data.len = size;
heap_data.fd_flags = O_RDWR | O_CLOEXEC;
if (ioctl(heap->heap_fd, DMA_HEAP_IOCTL_ALLOC, &heap_data) < 0)
return NULL;
fd = heap_data.fd;
buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (buf == MAP_FAILED) {
close(fd);
return NULL;
}
*dmabuf_fd = fd;
return buf;
}
void ibv_dmabuf_heap_free(void *buf, size_t size, int dmabuf_fd)
{
munmap(buf, size);
close(dmabuf_fd);
}
#else /* !HAVE_LINUX_DMA_HEAP_H */
struct ibv_dmabuf_heap *ibv_dmabuf_heap_cc_shared_init(void)
{
errno = EOPNOTSUPP;
return NULL;
}
void ibv_dmabuf_heap_destroy(struct ibv_dmabuf_heap *heap)
{
}
void *ibv_dmabuf_heap_alloc(struct ibv_dmabuf_heap *heap, size_t size,
int *dmabuf_fd)
{
errno = EOPNOTSUPP;
return NULL;
}
void ibv_dmabuf_heap_free(void *buf, size_t size, int dmabuf_fd)
{
}
#endif /* HAVE_LINUX_DMA_HEAP_H */