From 4a4b7b221205bf1e642507932fc5ccd054f77510 Mon Sep 17 00:00:00 2001 From: Mike Lothian Date: Sat, 13 Jun 2026 00:15:20 +0100 Subject: [PATCH 1/3] evdi: support the drm_atomic_state -> drm_atomic_commit rename drm-next (Linux 7.1) renamed the global atomic-state object and its allocator helpers: struct drm_atomic_state -> struct drm_atomic_commit drm_atomic_state_alloc/clear/put -> drm_atomic_commit_alloc/clear/put The atomic-helper vtable callbacks (.atomic_flush/.atomic_update/...) and the state accessors (drm_atomic_get_{new,old}_*_state()) now take a struct drm_atomic_commit *. evdi still uses the historical drm_atomic_state names throughout evdi_modeset.c, so it fails to build against >= 7.1 with incompatible pointer and function-pointer types. Alias the old identifiers to the new ones for KERNEL_VERSION(7, 1, 0) and later. The old names are fully gone from the tree, so these whole-token macros cannot collide with anything still in the headers. Signed-off-by: Mike Lothian --- module/evdi_drm_drv.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/module/evdi_drm_drv.h b/module/evdi_drm_drv.h index 71803d38..ea4bf4e0 100644 --- a/module/evdi_drm_drv.h +++ b/module/evdi_drm_drv.h @@ -38,6 +38,23 @@ #include #include +/* + * drm-next (>= 7.1.0) renamed the global atomic-state object and its helpers: + * struct drm_atomic_state -> struct drm_atomic_commit + * drm_atomic_state_alloc/clear/put -> drm_atomic_commit_alloc/clear/put + * The atomic-helper vtable callbacks (.atomic_flush/.atomic_update/...) and the + * state accessors (drm_atomic_get_{new,old}_*_state) now take a + * struct drm_atomic_commit *. evdi's source still uses the historical names, so + * alias them. The old identifiers are fully gone from the tree, so these + * whole-token macros are collision-free. + */ +#if KERNEL_VERSION(7, 1, 0) <= LINUX_VERSION_CODE +#define drm_atomic_state drm_atomic_commit +#define drm_atomic_state_alloc drm_atomic_commit_alloc +#define drm_atomic_state_clear drm_atomic_commit_clear +#define drm_atomic_state_put drm_atomic_commit_put +#endif + #include "evdi_debug.h" #include "tests/evdi_test.h" From f350c12774d7ad6184234194e838c10cf7fe7c9f Mon Sep 17 00:00:00 2001 From: Mike Lothian Date: Tue, 30 Jun 2026 14:38:52 +0100 Subject: [PATCH 2/3] evdi: react to USB_DEVICE_REMOVE in the USB unplug notifier evdi_platform_drv_usb() is installed with usb_register_notify(), so the USB core delivers it the USB_DEVICE_ADD / USB_DEVICE_REMOVE notifications (see usb_notify_add_device()/usb_notify_remove_device() in drivers/usb/core/notify.c), with the struct usb_device passed in @data. The handler instead compared @action against the bus-notifier constant BUS_NOTIFY_DEL_DEVICE. That enum value happens to equal USB_DEVICE_ADD (1), so the notifier body ran on every USB device *addition* and returned early on every *removal*. As a result evdi never reacted to its parent USB device (the dock) being unplugged. Test the correct USB_DEVICE_REMOVE constant so the handler runs when the parent USB device is removed. Signed-off-by: Mike Lothian Co-authored-by: Claude Opus 4.8 --- module/evdi_platform_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/evdi_platform_drv.c b/module/evdi_platform_drv.c index b83f12fe..6ed77f23 100644 --- a/module/evdi_platform_drv.c +++ b/module/evdi_platform_drv.c @@ -55,7 +55,7 @@ static int evdi_platform_drv_usb(__always_unused struct notifier_block *nb, if (!usb_dev) return 0; - if (action != BUS_NOTIFY_DEL_DEVICE) + if (action != USB_DEVICE_REMOVE) return 0; for (i = 0; i < EVDI_DEVICE_COUNT_MAX; ++i) { From 7c3c2bfec315861a6019e2b7bf92c8ac3bbaf45f Mon Sep 17 00:00:00 2001 From: Mike Lothian Date: Tue, 30 Jun 2026 14:39:41 +0100 Subject: [PATCH 3/3] evdi: destroy dynamic devices when their USB parent is removed When the parent USB device was unplugged the removal notifier detached the evdi platform device from it but never destroyed it. The teardown was gated on: if (pdev->dev.parent == &usb_dev->dev) but evdi platform devices are created with .parent = NULL (see evdi_platform_drv_create_new_device()); the USB relationship is tracked in evdi_platform_device_data::parent, not in dev.parent. The condition was therefore never true, so the DRM device was never unregistered, drm_dev_unplug() never ran, and userspace (Wayland compositors, Xorg) received no hot-unplug uevent and leaked the stale device. Have evdi_platform_device_unlink_if_linked_with() report whether it actually detached the device from this USB parent, and destroy the device when it did. Restrict the destroy to dynamically created devices (i >= evdi_initial_device_count); the statically pre-allocated devices are only detached, preserving their intended lifetime for static-list clients. Signed-off-by: Mike Lothian Co-authored-by: Claude Opus 4.8 --- module/evdi_platform_dev.c | 4 +++- module/evdi_platform_dev.h | 2 +- module/evdi_platform_drv.c | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/module/evdi_platform_dev.c b/module/evdi_platform_dev.c index 35d38113..86f92fac 100644 --- a/module/evdi_platform_dev.c +++ b/module/evdi_platform_dev.c @@ -140,7 +140,7 @@ void evdi_platform_device_link(struct platform_device *pdev, } } -void evdi_platform_device_unlink_if_linked_with(struct platform_device *pdev, +bool evdi_platform_device_unlink_if_linked_with(struct platform_device *pdev, struct device *parent) { struct evdi_platform_device_data *data = platform_get_drvdata(pdev); @@ -150,5 +150,7 @@ void evdi_platform_device_unlink_if_linked_with(struct platform_device *pdev, data->symlinked = false; data->parent = NULL; EVDI_INFO("Detached from parent device\n"); + return true; } + return false; } diff --git a/module/evdi_platform_dev.h b/module/evdi_platform_dev.h index 9c178ab7..9d8ea942 100644 --- a/module/evdi_platform_dev.h +++ b/module/evdi_platform_dev.h @@ -41,7 +41,7 @@ int evdi_platform_device_remove(struct platform_device *pdev); bool evdi_platform_device_is_free(struct platform_device *pdev); void evdi_platform_device_link(struct platform_device *pdev, struct device *parent); -void evdi_platform_device_unlink_if_linked_with(struct platform_device *pdev, +bool evdi_platform_device_unlink_if_linked_with(struct platform_device *pdev, struct device *parent); #endif diff --git a/module/evdi_platform_drv.c b/module/evdi_platform_drv.c index 6ed77f23..f52aed3d 100644 --- a/module/evdi_platform_drv.c +++ b/module/evdi_platform_drv.c @@ -62,8 +62,8 @@ static int evdi_platform_drv_usb(__always_unused struct notifier_block *nb, pdev = g_ctx.devices[i]; if (!pdev) continue; - evdi_platform_device_unlink_if_linked_with(pdev, &usb_dev->dev); - if (pdev->dev.parent == &usb_dev->dev) { + if (evdi_platform_device_unlink_if_linked_with(pdev, &usb_dev->dev) && + i >= evdi_initial_device_count) { EVDI_INFO("Parent USB removed. Removing evdi.%d\n", i); evdi_platform_dev_destroy(pdev); evdi_platform_drv_context_lock((&g_ctx));