[mutter] kms: Deal with GPUs being unplugged



commit f3660dc60e76b13e35f361a1ea6816f8b0af66d8
Author: Hans de Goede <hdegoede redhat com>
Date:   Mon Aug 5 14:08:08 2019 +0200

    kms: Deal with GPUs being unplugged
    
    Add meta-kms and meta-monitor-manager-kms listener for the udev
    device-removed signal and on this signal update the device state /
    re-enumerate the monitors, so that the monitors properly get updated
    to disconnected state on GPU removal.
    
    We really should also have meta-backend-native remove the GPU itself
    from our list of GPU objects. But that is more involved, see:
    https://gitlab.gnome.org/GNOME/mutter/issues/710
    
    This commit at least gets us to a point where we properly update the
    list of monitors when a GPU gets unplugged; and where we no longer
    crash the first time the user changes the monitor configuration after
    a GPU was unplugged.
    
    Specifically before this commit we would hit the first g_error () in
    meta_renderer_native_create_view () as soon as some monitor
    (re)configuration is done after a GPU was unplugged.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/713

 src/backends/native/meta-kms.c                 | 25 +++++++++++++++++++++++--
 src/backends/native/meta-monitor-manager-kms.c | 14 ++++++++++++++
 2 files changed, 37 insertions(+), 2 deletions(-)
---
diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c
index 641aaa198..13dc396d3 100644
--- a/src/backends/native/meta-kms.c
+++ b/src/backends/native/meta-kms.c
@@ -149,6 +149,7 @@ struct _MetaKms
   MetaBackend *backend;
 
   guint hotplug_handler_id;
+  guint removed_handler_id;
 
   MetaKmsImpl *impl;
   gboolean in_impl_task;
@@ -474,8 +475,7 @@ meta_kms_update_states_sync (MetaKms  *kms,
 }
 
 static void
-on_udev_hotplug (MetaUdev *udev,
-                 MetaKms  *kms)
+handle_hotplug_event (MetaKms *kms)
 {
   g_autoptr (GError) error = NULL;
 
@@ -483,6 +483,21 @@ on_udev_hotplug (MetaUdev *udev,
     g_warning ("Updating KMS state failed: %s", error->message);
 }
 
+static void
+on_udev_hotplug (MetaUdev *udev,
+                 MetaKms  *kms)
+{
+  handle_hotplug_event (kms);
+}
+
+static void
+on_udev_device_removed (MetaUdev    *udev,
+                        GUdevDevice *device,
+                        MetaKms     *kms)
+{
+  handle_hotplug_event (kms);
+}
+
 MetaBackend *
 meta_kms_get_backend (MetaKms *kms)
 {
@@ -525,6 +540,9 @@ meta_kms_new (MetaBackend  *backend,
 
   kms->hotplug_handler_id =
     g_signal_connect (udev, "hotplug", G_CALLBACK (on_udev_hotplug), kms);
+  kms->removed_handler_id =
+    g_signal_connect (udev, "device-removed",
+                      G_CALLBACK (on_udev_device_removed), kms);
 
   return kms;
 }
@@ -548,6 +566,9 @@ meta_kms_finalize (GObject *object)
   if (kms->hotplug_handler_id)
     g_signal_handler_disconnect (udev, kms->hotplug_handler_id);
 
+  if (kms->removed_handler_id)
+    g_signal_handler_disconnect (udev, kms->removed_handler_id);
+
   G_OBJECT_CLASS (meta_kms_parent_class)->finalize (object);
 }
 
diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index 9bac13576..26c2ddb61 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -76,6 +76,7 @@ struct _MetaMonitorManagerKms
   MetaMonitorManager parent_instance;
 
   guint hotplug_handler_id;
+  guint removed_handler_id;
 };
 
 struct _MetaMonitorManagerKmsClass
@@ -484,6 +485,14 @@ on_udev_hotplug (MetaUdev           *udev,
   handle_hotplug_event (manager);
 }
 
+static void
+on_udev_device_removed (MetaUdev           *udev,
+                        GUdevDevice        *device,
+                        MetaMonitorManager *manager)
+{
+  handle_hotplug_event (manager);
+}
+
 static void
 meta_monitor_manager_kms_connect_hotplug_handler (MetaMonitorManagerKms *manager_kms)
 {
@@ -494,6 +503,9 @@ meta_monitor_manager_kms_connect_hotplug_handler (MetaMonitorManagerKms *manager
   manager_kms->hotplug_handler_id =
     g_signal_connect_after (udev, "hotplug",
                             G_CALLBACK (on_udev_hotplug), manager);
+  manager_kms->removed_handler_id =
+    g_signal_connect_after (udev, "device-removed",
+                            G_CALLBACK (on_udev_device_removed), manager);
 }
 
 static void
@@ -505,6 +517,8 @@ meta_monitor_manager_kms_disconnect_hotplug_handler (MetaMonitorManagerKms *mana
 
   g_signal_handler_disconnect (udev, manager_kms->hotplug_handler_id);
   manager_kms->hotplug_handler_id = 0;
+  g_signal_handler_disconnect (udev, manager_kms->removed_handler_id);
+  manager_kms->removed_handler_id = 0;
 }
 
 void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]