[mutter] gpu-kms: Don't add outputs without modes
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] gpu-kms: Don't add outputs without modes
- Date: Mon, 5 Feb 2018 02:48:17 +0000 (UTC)
commit d092e913d6541ed801d1d17af66e6ea715790d5d
Author: Jonas Ådahl <jadahl gmail com>
Date: Fri Nov 3 15:55:07 2017 +0800
gpu-kms: Don't add outputs without modes
There seems to be a kernel race when one disconnects an external
monitor connected to a DisplayPort via a USB-C adapter. The race
results in a connector being reported as connected, but without any
modes supported.
This had the side effect that we tried to set a preferred mode to
the first listed mode, but as no modes were available, we instead tried
to dereference the first element of a NULL array, causing a
segmentation fault.
Mitigate this by skipping adding output if no supported modes are
advertised and the output doesn't support scaling, while moving the
fallback path for calculating a preferred output mode to after possibly
adding the common modes, to avoid the unvolentary NULL dereference.
https://bugzilla.gnome.org/show_bug.cgi?id=789501
src/backends/native/meta-gpu-kms.c | 14 ++++++++--
src/backends/native/meta-output-kms.c | 51 ++++++++++++++++++++++-------------
src/backends/native/meta-output-kms.h | 9 ++++---
3 files changed, 50 insertions(+), 24 deletions(-)
---
diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c
index 0ab345ba9..d8b512342 100644
--- a/src/backends/native/meta-gpu-kms.c
+++ b/src/backends/native/meta-gpu-kms.c
@@ -675,11 +675,21 @@ init_outputs (MetaGpuKms *gpu_kms,
{
MetaOutput *output;
MetaOutput *old_output;
+ GError *error = NULL;
old_output = find_output_by_id (old_outputs, connector->connector_id);
output = meta_create_kms_output (gpu_kms, connector, resources,
- old_output);
- outputs = g_list_prepend (outputs, output);
+ old_output,
+ &error);
+ if (!output)
+ {
+ g_warning ("Failed to create KMS output: %s", error->message);
+ g_error_free (error);
+ }
+ else
+ {
+ outputs = g_list_prepend (outputs, output);
+ }
}
}
diff --git a/src/backends/native/meta-output-kms.c b/src/backends/native/meta-output-kms.c
index 1b633b155..5668be51c 100644
--- a/src/backends/native/meta-output-kms.c
+++ b/src/backends/native/meta-output-kms.c
@@ -438,9 +438,10 @@ compare_modes (const void *one,
return g_strcmp0 (b->name, a->name);
}
-static void
-init_output_modes (MetaOutput *output,
- MetaGpuKms *gpu_kms)
+static gboolean
+init_output_modes (MetaOutput *output,
+ MetaGpuKms *gpu_kms,
+ GError **error)
{
MetaOutputKms *output_kms = output->driver_private;
unsigned int i;
@@ -460,15 +461,35 @@ init_output_modes (MetaOutput *output,
output->preferred_mode = output->modes[i];
}
+ /* FIXME: MSC feature bit? */
+ /* Presume that if the output supports scaling, then we have
+ * a panel fitter capable of adjusting any mode to suit.
+ */
+ if (output_kms->has_scaling)
+ add_common_modes (output, gpu_kms);
+
+ if (!output->modes)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "No modes available");
+ return FALSE;
+ }
+
+ qsort (output->modes, output->n_modes,
+ sizeof (MetaCrtcMode *), compare_modes);
+
if (!output->preferred_mode)
output->preferred_mode = output->modes[0];
+
+ return TRUE;
}
MetaOutput *
-meta_create_kms_output (MetaGpuKms *gpu_kms,
- drmModeConnector *connector,
- MetaKmsResources *resources,
- MetaOutput *old_output)
+meta_create_kms_output (MetaGpuKms *gpu_kms,
+ drmModeConnector *connector,
+ MetaKmsResources *resources,
+ MetaOutput *old_output,
+ GError **error)
{
MetaGpu *gpu = META_GPU (gpu_kms);
MetaOutput *output;
@@ -527,17 +548,11 @@ meta_create_kms_output (MetaGpuKms *gpu_kms,
output->height_mm = connector->mmHeight;
}
- init_output_modes (output, gpu_kms);
-
- /* FIXME: MSC feature bit? */
- /* Presume that if the output supports scaling, then we have
- * a panel fitter capable of adjusting any mode to suit.
- */
- if (output_kms->has_scaling)
- add_common_modes (output, gpu_kms);
-
- qsort (output->modes, output->n_modes,
- sizeof (MetaCrtcMode *), compare_modes);
+ if (!init_output_modes (output, gpu_kms, error))
+ {
+ g_object_unref (output);
+ return NULL;
+ }
output_kms->n_encoders = connector->count_encoders;
output_kms->encoders = g_new0 (drmModeEncoderPtr, output_kms->n_encoders);
diff --git a/src/backends/native/meta-output-kms.h b/src/backends/native/meta-output-kms.h
index ca811b92b..cbca02ef5 100644
--- a/src/backends/native/meta-output-kms.h
+++ b/src/backends/native/meta-output-kms.h
@@ -35,9 +35,10 @@ gboolean meta_output_kms_can_clone (MetaOutput *output,
GBytes * meta_output_kms_read_edid (MetaOutput *output);
-MetaOutput * meta_create_kms_output (MetaGpuKms *gpu_kms,
- drmModeConnector *connector,
- MetaKmsResources *resources,
- MetaOutput *old_output);
+MetaOutput * meta_create_kms_output (MetaGpuKms *gpu_kms,
+ drmModeConnector *connector,
+ MetaKmsResources *resources,
+ MetaOutput *old_output,
+ GError **error);
#endif /* META_OUTPUT_KMS_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]