native: Release output device files that are unused

In order to make it possible to e.g. unload an unused DRM device, we
need to make sure that we don't keep the file descriptor open if we
don't need it; otherwise we block anyone from unloading the
corresponding module.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1828>
This commit is contained in:
Jonas Ådahl
2021-04-12 16:25:53 +02:00
parent 3c47661b78
commit ce5a5789bb
11 changed files with 426 additions and 71 deletions

View File

@ -655,6 +655,7 @@ retry_page_flips (gpointer user_data)
g_critical ("Failed to page flip: %s", error->message);
meta_kms_page_flip_data_discard_in_impl (page_flip_data, error);
meta_kms_impl_device_unhold_fd (impl_device);
}
else
{
@ -977,6 +978,7 @@ dispatch_page_flip (MetaKmsImplDevice *impl_device,
fb_id = 0;
drm_mode = cached_mode_set->drm_mode;
refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode);
meta_kms_impl_device_hold_fd (impl_device);
schedule_retry_page_flip (impl_device_simple,
crtc,
fb_id,
@ -1016,6 +1018,8 @@ dispatch_page_flip (MetaKmsImplDevice *impl_device,
}
else
{
meta_kms_impl_device_hold_fd (impl_device);
impl_device_simple->posted_page_flip_datas =
g_list_prepend (impl_device_simple->posted_page_flip_datas,
page_flip_data);
@ -1367,6 +1371,8 @@ page_flip_handler (int fd,
page_flip_data,
meta_kms_crtc_get_id (crtc));
meta_kms_impl_device_unhold_fd (impl_device);
meta_kms_impl_device_handle_page_flip_callback (impl_device, page_flip_data);
impl_device_simple->posted_page_flip_datas =
g_list_remove (impl_device_simple->posted_page_flip_datas,
@ -1465,6 +1471,14 @@ meta_kms_impl_device_simple_handle_page_flip_callback (MetaKmsImplDevice *impl
}
}
static void
dispose_page_flip_data (MetaKmsPageFlipData *page_flip_data,
MetaKmsImplDevice *impl_device)
{
meta_kms_page_flip_data_discard_in_impl (page_flip_data, NULL);
meta_kms_impl_device_unhold_fd (impl_device);
}
static void
meta_kms_impl_device_simple_discard_pending_page_flips (MetaKmsImplDevice *impl_device)
{
@ -1489,7 +1503,7 @@ meta_kms_impl_device_simple_discard_pending_page_flips (MetaKmsImplDevice *impl_
meta_kms_impl_device_get_path (
meta_kms_page_flip_data_get_impl_device (page_flip_data)));
meta_kms_page_flip_data_discard_in_impl (page_flip_data, NULL);
dispose_page_flip_data (page_flip_data, impl_device);
retry_page_flip_data_free (retry_page_flip_data);
}
g_clear_pointer (&impl_device_simple->pending_page_flip_retries, g_list_free);
@ -1505,8 +1519,8 @@ meta_kms_impl_device_simple_prepare_shutdown (MetaKmsImplDevice *impl_device)
META_KMS_IMPL_DEVICE_SIMPLE (impl_device);
g_list_foreach (impl_device_simple->posted_page_flip_datas,
(GFunc) meta_kms_page_flip_data_discard_in_impl,
NULL);
(GFunc) dispose_page_flip_data,
impl_device);
g_clear_list (&impl_device_simple->posted_page_flip_datas, NULL);
}
@ -1515,18 +1529,16 @@ meta_kms_impl_device_simple_finalize (GObject *object)
{
MetaKmsImplDeviceSimple *impl_device_simple =
META_KMS_IMPL_DEVICE_SIMPLE (object);
MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_simple);
g_list_free_full (impl_device_simple->pending_page_flip_retries,
(GDestroyNotify) retry_page_flip_data_free);
dispatch_page_flip_datas (&impl_device_simple->posted_page_flip_datas,
(GFunc) meta_kms_page_flip_data_discard_in_impl,
NULL);
dispatch_page_flip_datas (&impl_device_simple->postponed_page_flip_datas,
(GFunc) meta_kms_page_flip_data_discard_in_impl,
NULL);
(GFunc) dispose_page_flip_data,
impl_device);
dispatch_page_flip_datas (&impl_device_simple->postponed_mode_set_fallback_datas,
(GFunc) meta_kms_page_flip_data_discard_in_impl,
NULL);
(GFunc) dispose_page_flip_data,
impl_device);
g_assert (!impl_device_simple->posted_page_flip_datas);
@ -1548,7 +1560,6 @@ meta_kms_impl_device_simple_open_device_file (MetaKmsImplDevice *impl_device,
MetaDevicePool *device_pool =
meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend));
g_autoptr (MetaDeviceFile) device_file = NULL;
int fd;
device_file = meta_device_pool_open (device_pool, path,
META_DEVICE_FILE_FLAG_TAKE_CONTROL,
@ -1556,13 +1567,26 @@ meta_kms_impl_device_simple_open_device_file (MetaKmsImplDevice *impl_device,
if (!device_file)
return NULL;
fd = meta_device_file_get_fd (device_file);
if (drmSetClientCap (fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) != 0)
if (!meta_device_file_has_tag (device_file,
META_DEVICE_FILE_TAG_KMS,
META_KMS_DEVICE_FILE_TAG_SIMPLE))
{
g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED,
"DRM_CLIENT_CAP_UNIVERSAL_PLANES not supported");
return NULL;
int fd = meta_device_file_get_fd (device_file);
g_warn_if_fail (!meta_device_file_has_tag (device_file,
META_DEVICE_FILE_TAG_KMS,
META_KMS_DEVICE_FILE_TAG_ATOMIC));
if (drmSetClientCap (fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) != 0)
{
g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED,
"DRM_CLIENT_CAP_UNIVERSAL_PLANES not supported");
return NULL;
}
meta_device_file_tag (device_file,
META_DEVICE_FILE_TAG_KMS,
META_KMS_DEVICE_FILE_TAG_SIMPLE);
}
return g_steal_pointer (&device_file);