Untitled

 avatar
unknown
plain_text
a month ago
6.0 kB
2
Indexable
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include <libdrm/drm.h>
#include <xf86drm.h>
#include <stdbool.h>
#include "/usr/include/libdrm/drm.h"
#include "/usr/include/xf86drm.h"
#include <stdbool.h>

// DRM formats for testing
#define DRM_FORMAT_ARGB8888 0x34325241
#define DRM_FORMAT_XRGB8888 0x34325258

struct udmabuf_create {
    uint32_t memfd;
    uint32_t offset;
    uint32_t size;
    uint32_t flags;
};

#define UDMABUF_CREATE _IOW('u', 0x42, struct udmabuf_create)

static bool test_basic_memory(int fd, size_t size) {
    printf("\nTesting basic memory operations...\n");
    
    void *buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (buffer == MAP_FAILED) {
        printf("Failed to mmap: %s\n", strerror(errno));
        return false;
    }

    // Write pattern
    uint32_t *ptr = buffer;
    for (size_t i = 0; i < size/4; i++) {
        ptr[i] = i;
    }

    // Read and verify
    bool success = true;
    for (size_t i = 0; i < size/4; i++) {
        if (ptr[i] != i) {
            printf("Data mismatch at offset %zu: expected %zu, got %u\n", 
                   i, i, ptr[i]);
            success = false;
            break;
        }
    }

    munmap(buffer, size);
    return success;
}

static bool test_gpu_access(int dma_buf_fd) {
    printf("\nTesting GPU accessibility...\n");
    
    // Try to open the render node
    int drm_fd = open("/dev/dri/renderD128", O_RDWR);
    if (drm_fd < 0) {
        printf("Failed to open render node: %s\n", strerror(errno));
        return false;
    }

    // Get DRM version to verify it's a GPU device
    drmVersionPtr version = drmGetVersion(drm_fd);
    if (!version) {
        printf("Failed to get DRM version: %s\n", strerror(errno));
        close(drm_fd);
        return false;
    }
    printf("DRM Device: %s\n", version->name);
    drmFreeVersion(version);

    // Try to import the buffer
    struct drm_prime_handle prime;
    memset(&prime, 0, sizeof(prime));
    prime.fd = dma_buf_fd;
    prime.flags = DRM_CLOEXEC;

    if (ioctl(drm_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime) == -1) {
        printf("Failed to import buffer to GPU: %s\n", strerror(errno));
        close(drm_fd);
        return false;
    }

    printf("Successfully imported buffer to GPU (handle: %u)\n", prime.handle);
    
    // Clean up
    struct drm_gem_close close_arg;
    memset(&close_arg, 0, sizeof(close_arg));
    close_arg.handle = prime.handle;
    ioctl(drm_fd, DRM_IOCTL_GEM_CLOSE, &close_arg);
    
    close(drm_fd);
    return true;
}

static bool test_sync_operations(int fd) {
    printf("\nTesting sync operations...\n");
    
    // Try to read sync mode
    char sync_mode[32];
    FILE *fp = fopen("/sys/class/u-dma-buf/udmabuf0/sync_mode", "r");
    if (fp) {
        fgets(sync_mode, sizeof(sync_mode), fp);
        printf("Current sync mode: %s", sync_mode);
        fclose(fp);
    } else {
        printf("Cannot read sync mode: %s\n", strerror(errno));
    }

    // Try sync for device access
    fp = fopen("/sys/class/u-dma-buf/udmabuf0/sync_for_device", "w");
    if (fp) {
        fprintf(fp, "1");
        fclose(fp);
        printf("sync_for_device successful\n");
    } else {
        printf("sync_for_device failed: %s\n", strerror(errno));
        return false;
    }

    // Try sync for CPU access
    fp = fopen("/sys/class/u-dma-buf/udmabuf0/sync_for_cpu", "w");
    if (fp) {
        fprintf(fp, "1");
        fclose(fp);
        printf("sync_for_cpu successful\n");
    } else {
        printf("sync_for_cpu failed: %s\n", strerror(errno));
        return false;
    }

    return true;
}

static void print_buffer_info(int fd) {
    printf("\nBuffer Information:\n");
    FILE *fp;
    char buf[256];

    // Read phys_addr
    fp = fopen("/sys/class/u-dma-buf/udmabuf0/phys_addr", "r");
    if (fp) {
        fgets(buf, sizeof(buf), fp);
        printf("Physical address: %s", buf);
        fclose(fp);
    }

    // Read size
    fp = fopen("/sys/class/u-dma-buf/udmabuf0/size", "r");
    if (fp) {
        fgets(buf, sizeof(buf), fp);
        printf("Buffer size: %s", buf);
        fclose(fp);
    }

    // Read driver version
    fp = fopen("/sys/class/u-dma-buf/udmabuf0/driver_version", "r");
    if (fp) {
        fgets(buf, sizeof(buf), fp);
        printf("Driver version: %s", buf);
        fclose(fp);
    }
}

int main() {
    int fd;
    bool all_tests_passed = true;
    const size_t test_size = 4194304; // 4MB

    printf("Starting comprehensive DMA buffer tests...\n");

    // Open the DMA buffer device
    fd = open("/dev/udmabuf0", O_RDWR);
    if (fd < 0) {
        printf("Failed to open /dev/udmabuf0: %s\n", strerror(errno));
        return 1;
    }

    // Print initial buffer information
    print_buffer_info(fd);

    // Test 1: Basic memory operations
    if (!test_basic_memory(fd, test_size)) {
        printf("Basic memory test FAILED\n");
        all_tests_passed = false;
    } else {
        printf("Basic memory test PASSED\n");
    }

    // Test 2: GPU accessibility
    if (!test_gpu_access(fd)) {
        printf("GPU accessibility test FAILED\n");
        all_tests_passed = false;
    } else {
        printf("GPU accessibility test PASSED\n");
    }

    // Test 3: Sync operations
    if (!test_sync_operations(fd)) {
        printf("Sync operations test FAILED\n");
        all_tests_passed = false;
    } else {
        printf("Sync operations test PASSED\n");
    }

    // Cleanup
    close(fd);

    printf("\nTest Summary:\n");
    printf("Overall result: %s\n", all_tests_passed ? "PASSED" : "FAILED");
    
    return all_tests_passed ? 0 : 1;
}
Leave a Comment