From: Aaron Ruby Date: Fri, 10 Jan 2025 22:17:56 +0000 (-0500) Subject: [PATCH] gfxstream: Make the virtgpu device discovery for LinuxVirtGpu more robust X-Git-Tag: archive/raspbian/25.0.7-2+rpi1^2^2^2^2^2~5 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=c2b29234d577aa431509dbd7b9940f664eb105fe;p=mesa.git [PATCH] gfxstream: Make the virtgpu device discovery for LinuxVirtGpu more robust Part-of: Gbp-Pq: Name gfxstream-make-virtgpu-discovery-more-robust.diff --- diff --git a/src/gfxstream/guest/platform/linux/LinuxVirtGpu.h b/src/gfxstream/guest/platform/linux/LinuxVirtGpu.h index 46daa0d59..a92a67a96 100644 --- a/src/gfxstream/guest/platform/linux/LinuxVirtGpu.h +++ b/src/gfxstream/guest/platform/linux/LinuxVirtGpu.h @@ -6,6 +6,7 @@ #pragma once #include "VirtGpu.h" +#include class LinuxVirtGpuResource : public std::enable_shared_from_this, public VirtGpuResource { @@ -69,4 +70,15 @@ class LinuxVirtGpuDevice : public VirtGpuDevice { private: int64_t mDeviceHandle; struct VirtGpuCaps mCaps; + + int openDevice(const drmDevicePtr dev); + + bool mHasPrimary; + int mPrimaryMajor; + int mPrimaryMinor; + int mRenderMajor; + int mRenderMinor; + + int mBusType; + drmPciBusInfo mPciBusInfo; }; diff --git a/src/gfxstream/guest/platform/linux/LinuxVirtGpuDevice.cpp b/src/gfxstream/guest/platform/linux/LinuxVirtGpuDevice.cpp index 9eb6b64ec..d085a3a91 100644 --- a/src/gfxstream/guest/platform/linux/LinuxVirtGpuDevice.cpp +++ b/src/gfxstream/guest/platform/linux/LinuxVirtGpuDevice.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -20,6 +21,16 @@ #include "util/log.h" #include "virtgpu_gfxstream_protocol.h" +#ifdef MAJOR_IN_MKDEV +#include +#endif +#ifdef MAJOR_IN_SYSMACROS +#include +#endif + +#define VIRTGPU_PCI_VENDOR_ID 0x1af4 +#define VIRTGPU_PCI_DEVICE_ID 0x1050 + #define VIRTGPU_PARAM_CREATE_FENCE_PASSING 9 /* Fence passing */ #define VIRTGPU_PARAM_CREATE_GUEST_HANDLE 10 /* Host OS handle can be created from guest memory. */ @@ -28,6 +39,85 @@ static inline uint32_t align_up(uint32_t n, uint32_t a) { return ((n + a - 1) / a) * a; } +int +LinuxVirtGpuDevice::openDevice(const drmDevicePtr dev) +{ + bool supported_bus = false; + + switch (dev->bustype) { + case DRM_BUS_PCI: + if (dev->deviceinfo.pci->vendor_id == VIRTGPU_PCI_VENDOR_ID && + dev->deviceinfo.pci->device_id == VIRTGPU_PCI_DEVICE_ID) + supported_bus = true; + break; + case DRM_BUS_PLATFORM: + supported_bus = true; + break; + default: + break; + } + + if (!supported_bus || !(dev->available_nodes & (1 << DRM_NODE_RENDER))) { + const char *name = "unknown"; + for (uint32_t i = 0; i < DRM_NODE_MAX; i++) { + if (dev->available_nodes & (1 << i)) { + name = dev->nodes[i]; + break; + } + } + mesa_logd("skipping DRM device %s", name); + return -1; + } + + const char *primary_path = dev->nodes[DRM_NODE_PRIMARY]; + const char *node_path = dev->nodes[DRM_NODE_RENDER]; + + int fd = open(node_path, O_RDWR | O_CLOEXEC); + if (fd < 0) { + mesa_logd("failed to open %s", node_path); + return -1; + } + + drmVersionPtr version = drmGetVersion(fd); + if (!version || strcmp(version->name, "virtio_gpu") || + version->version_major != 0) { + if (version) { + mesa_logd("unknown DRM driver %s version %d", + version->name, version->version_major); + } else { + mesa_logd("failed to get DRM driver version"); + } + if (version) + drmFreeVersion(version); + close(fd); + return -1; + } + + struct stat st; + if (stat(primary_path, &st) == 0) { + mHasPrimary = true; + mPrimaryMajor = major(st.st_rdev); + mPrimaryMinor = minor(st.st_rdev); + } else { + mHasPrimary = false; + mPrimaryMajor = 0; + mPrimaryMinor = 0; + } + stat(node_path, &st); + mRenderMajor = major(st.st_rdev); + mRenderMinor = minor(st.st_rdev); + + mBusType = dev->bustype; + if (dev->bustype == DRM_BUS_PCI) + mPciBusInfo = *dev->businfo.pci; + + drmFreeVersion(version); + + mesa_logd("using DRM device %s", node_path); + + return fd; +} + LinuxVirtGpuDevice::LinuxVirtGpuDevice(enum VirtGpuCapset capset, int32_t descriptor) : VirtGpuDevice(capset) { struct VirtGpuParam params[] = { @@ -52,11 +142,27 @@ LinuxVirtGpuDevice::LinuxVirtGpuDevice(enum VirtGpuCapset capset, int32_t descri #endif if (descriptor < 0) { - mDeviceHandle = static_cast(drmOpenRender(128)); - if (mDeviceHandle < 0) { - mesa_loge("Failed to open rendernode: %s", strerror(errno)); + drmDevicePtr devs[8]; + int count = drmGetDevices2(0, devs, ARRAY_SIZE(devs)); + if (count < 0) { + mesa_loge("failed to enumerate DRM devices"); return; } + + int fd = -1; + for (int i = 0; i < count; i++) { + fd = openDevice(devs[i]); + if (fd >= 0) break; + } + + drmFreeDevices(devs, count); + + if (fd < 0) { + mesa_loge("Failed to open the virtio_gpu device."); + return; + } + + mDeviceHandle = static_cast(fd); } else { mDeviceHandle = dup(descriptor); if (mDeviceHandle < 0) { diff --git a/src/gfxstream/guest/vulkan/gfxstream_vk_device.cpp b/src/gfxstream/guest/vulkan/gfxstream_vk_device.cpp index 971611445..f5e6a685f 100644 --- a/src/gfxstream/guest/vulkan/gfxstream_vk_device.cpp +++ b/src/gfxstream/guest/vulkan/gfxstream_vk_device.cpp @@ -368,9 +368,10 @@ VkResult gfxstream_vk_CreateInstance(const VkInstanceCreateInfo* pCreateInfo, return vk_error(NULL, result); } + // Note: Do not support try_create_for_drm. virtio_gpu DRM device opened in + // init_renderer above, which can still enumerate multiple physical devices on the host. instance->vk.physical_devices.enumerate = gfxstream_vk_enumerate_devices; instance->vk.physical_devices.destroy = gfxstream_vk_destroy_physical_device; - // TODO: instance->vk.physical_devices.try_create_for_drm (?) *pInstance = gfxstream_vk_instance_to_handle(instance); return VK_SUCCESS;