From d870a12c3abfe0d2347996c37784a34b37457b7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Fri, 1 Aug 2025 11:05:17 +0200 Subject: [PATCH] xf86drm: Add faux bus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linux 6.14 included a new type of bus, the "faux" bus [1]. The next version of Linux (v6.16) will move the VKMS driver to the faux bus. See kernel commit 5686601908d8 ("drm/vkms: convert to use faux_device") for more details. Add support for the faux bus so drmGetDeviceFromDevId(), drmGetDevices() and drmGetDevices2() return the devices on it. [1] https://lore.kernel.org/all/2025021023-sandstorm-precise-9f5d@gregkh/ Reviewed-by: Dmitry Baryshkov Signed-off-by: José Expósito --- tests/drmdevice.c | 6 ++++ xf86drm.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++ xf86drm.h | 6 ++++ 3 files changed, 89 insertions(+) diff --git a/tests/drmdevice.c b/tests/drmdevice.c index b4b62d9c..9ddfc8dd 100644 --- a/tests/drmdevice.c +++ b/tests/drmdevice.c @@ -98,6 +98,12 @@ print_device_info(drmDevicePtr device, int i, bool print_revision) printf(" %s\n", *compatible); compatible++; } + } else if (device->bustype == DRM_BUS_FAUX) { + printf("| +-> faux\n"); + + printf("+-> deviceinfo\n"); + printf(" +-> faux\n"); + printf(" +-> name %s\n", device->deviceinfo.faux->name); } else { printf("Unknown/unhandled bustype\n"); } diff --git a/xf86drm.c b/xf86drm.c index 06fdb85f..e587d714 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -3592,6 +3593,7 @@ static int get_subsystem_type(const char *device_path) { "/spi", DRM_BUS_PLATFORM }, { "/host1x", DRM_BUS_HOST1X }, { "/virtio", DRM_BUS_VIRTIO }, + { "/faux", DRM_BUS_FAUX }, }; strncpy(path, device_path, PATH_MAX); @@ -3795,6 +3797,9 @@ drm_public int drmDevicesEqual(drmDevicePtr a, drmDevicePtr b) case DRM_BUS_HOST1X: return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo)) == 0; + case DRM_BUS_FAUX: + return memcmp(a->deviceinfo.faux, b->deviceinfo.faux, sizeof(drmFauxDeviceInfo)) == 0; + default: break; } @@ -4015,6 +4020,12 @@ static void drmFreeHost1xDevice(drmDevicePtr device) } } +static void drmFreeFauxDevice(drmDevicePtr device) +{ + if (device->deviceinfo.faux) + free(device->deviceinfo.faux->name); +} + drm_public void drmFreeDevice(drmDevicePtr *device) { if (device == NULL) @@ -4029,6 +4040,10 @@ drm_public void drmFreeDevice(drmDevicePtr *device) case DRM_BUS_HOST1X: drmFreeHost1xDevice(*device); break; + + case DRM_BUS_FAUX: + drmFreeFauxDevice(*device); + break; } } @@ -4457,6 +4472,65 @@ free_device: return ret; } +static int drmParseFauxDeviceInfo(int maj, int min, drmFauxDeviceInfoPtr info) +{ +#ifdef __linux__ + char path[PATH_MAX + 1] = ""; + char real_path[PATH_MAX + 1] = ""; + char *name; + + snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min); + + if (!realpath(path, real_path)) + return -errno; + + name = basename(real_path); + if (!name) + return -ENOENT; + + info->name = strdup(name); + if (!info->name) + return -errno; + + return 0; +#else +#warning "Missing implementation of drmParseFauxDeviceInfo" + return -EINVAL; +#endif +} + +static int drmProcessFauxDevice(drmDevicePtr *device, + const char *node, int node_type, + int maj, int min, bool fetch_deviceinfo, + uint32_t flags) +{ + drmDevicePtr dev; + char *ptr; + int ret; + + dev = drmDeviceAlloc(node_type, node, 0, sizeof(drmFauxDeviceInfo), &ptr); + if (!dev) + return -ENOMEM; + + dev->bustype = DRM_BUS_FAUX; + + if (fetch_deviceinfo) { + dev->deviceinfo.faux = (drmFauxDeviceInfoPtr)ptr; + + ret = drmParseFauxDeviceInfo(maj, min, dev->deviceinfo.faux); + if (ret < 0) + goto free_device; + } + + *device = dev; + + return 0; + +free_device: + free(dev); + return ret; +} + static int process_device(drmDevicePtr *device, const char *d_name, int req_subsystem_type, @@ -4509,6 +4583,9 @@ process_device(drmDevicePtr *device, const char *d_name, case DRM_BUS_HOST1X: return drmProcessHost1xDevice(device, node, node_type, maj, min, fetch_deviceinfo, flags); + case DRM_BUS_FAUX: + return drmProcessFauxDevice(device, node, node_type, maj, min, + fetch_deviceinfo, flags); default: return -1; } diff --git a/xf86drm.h b/xf86drm.h index 6d91dfbd..6bfe2782 100644 --- a/xf86drm.h +++ b/xf86drm.h @@ -843,6 +843,7 @@ extern char *drmGetRenderDeviceNameFromFd(int fd); #define DRM_BUS_USB 1 #define DRM_BUS_PLATFORM 2 #define DRM_BUS_HOST1X 3 +#define DRM_BUS_FAUX 4 typedef struct _drmPciBusInfo { uint16_t domain; @@ -889,6 +890,10 @@ typedef struct _drmHost1xDeviceInfo { char **compatible; /* NULL terminated list of compatible strings */ } drmHost1xDeviceInfo, *drmHost1xDeviceInfoPtr; +typedef struct _drmFauxDeviceInfo { + char *name; +} drmFauxDeviceInfo, *drmFauxDeviceInfoPtr; + typedef struct _drmDevice { char **nodes; /* DRM_NODE_MAX sized array */ int available_nodes; /* DRM_NODE_* bitmask */ @@ -904,6 +909,7 @@ typedef struct _drmDevice { drmUsbDeviceInfoPtr usb; drmPlatformDeviceInfoPtr platform; drmHost1xDeviceInfoPtr host1x; + drmFauxDeviceInfoPtr faux; } deviceinfo; } drmDevice, *drmDevicePtr;