kms: Don't enter power saving via updates

The way device backends implement power saving differ, and power saving
needs to contain nothing incompatible in the same update. Make it
impossible to e.g. mode set, page flip, etc while entering power save by
not using MetaKmsUpdate's at all for this.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2159>
This commit is contained in:
Jonas Ådahl 2021-06-28 10:11:31 +02:00 committed by Marge Bot
parent 3472ff50ce
commit 2d7a8c3ce9
15 changed files with 165 additions and 133 deletions

View File

@ -43,6 +43,8 @@ const char * meta_kms_connector_get_prop_name (MetaKmsConnector *connector,
MetaKmsUpdateChanges meta_kms_connector_update_state (MetaKmsConnector *connector,
drmModeRes *drm_resources);
void meta_kms_connector_disable (MetaKmsConnector *connector);
void meta_kms_connector_predict_state (MetaKmsConnector *connector,
MetaKmsUpdate *update);

View File

@ -753,6 +753,18 @@ meta_kms_connector_update_state (MetaKmsConnector *connector,
return changes;
}
void
meta_kms_connector_disable (MetaKmsConnector *connector)
{
MetaKmsConnectorState *current_state;
current_state = connector->current_state;
if (!current_state)
return;
current_state->current_crtc_id = 0;
}
void
meta_kms_connector_predict_state (MetaKmsConnector *connector,
MetaKmsUpdate *update)
@ -766,9 +778,6 @@ meta_kms_connector_predict_state (MetaKmsConnector *connector,
if (!current_state)
return;
if (meta_kms_update_is_power_save (update))
current_state->current_crtc_id = 0;
mode_sets = meta_kms_update_get_mode_sets (update);
for (l = mode_sets; l; l = l->next)
{

View File

@ -40,6 +40,8 @@ MetaKmsCrtc * meta_kms_crtc_new (MetaKmsImplDevice *impl_device,
MetaKmsUpdateChanges meta_kms_crtc_update_state (MetaKmsCrtc *crtc);
void meta_kms_crtc_disable (MetaKmsCrtc *crtc);
void meta_kms_crtc_predict_state (MetaKmsCrtc *crtc,
MetaKmsUpdate *update);

View File

@ -278,14 +278,7 @@ out:
}
void
meta_kms_crtc_predict_state (MetaKmsCrtc *crtc,
MetaKmsUpdate *update)
{
GList *mode_sets;
GList *crtc_gammas;
GList *l;
if (meta_kms_update_is_power_save (update))
meta_kms_crtc_disable (MetaKmsCrtc *crtc)
{
crtc->current_state.is_active = FALSE;
crtc->current_state.rect = (MetaRectangle) { 0 };
@ -293,6 +286,14 @@ meta_kms_crtc_predict_state (MetaKmsCrtc *crtc,
crtc->current_state.drm_mode = (drmModeModeInfo) { 0 };
}
void
meta_kms_crtc_predict_state (MetaKmsCrtc *crtc,
MetaKmsUpdate *update)
{
GList *mode_sets;
GList *crtc_gammas;
GList *l;
mode_sets = meta_kms_update_get_mode_sets (update);
for (l = mode_sets; l; l = l->next)
{

View File

@ -231,6 +231,28 @@ meta_kms_device_get_fallback_modes (MetaKmsDevice *device)
return device->fallback_modes;
}
static gpointer
disable_device_in_impl (MetaKmsImpl *impl,
gpointer user_data,
GError **error)
{
MetaKmsImplDevice *impl_device = user_data;
meta_kms_impl_device_disable (impl_device);
return GINT_TO_POINTER (TRUE);
}
void
meta_kms_device_disable (MetaKmsDevice *device)
{
meta_assert_not_in_kms_impl (device->kms);
meta_kms_run_impl_task_sync (device->kms, disable_device_in_impl,
device->impl_device,
NULL);
}
MetaKmsUpdateChanges
meta_kms_device_update_states_in_impl (MetaKmsDevice *device,
uint32_t crtc_id,

View File

@ -77,6 +77,9 @@ MetaKmsFeedback * meta_kms_device_process_update_sync (MetaKmsDevice *device
MetaKmsUpdate *update,
MetaKmsUpdateFlag flags);
META_EXPORT_TEST
void meta_kms_device_disable (MetaKmsDevice *device);
MetaKmsDevice * meta_kms_device_new (MetaKms *kms,
const char *path,
MetaKmsDeviceFlag flags,

View File

@ -904,21 +904,6 @@ disable_planes_and_connectors (MetaKmsImplDevice *impl_device,
return TRUE;
}
static gboolean
process_power_save (MetaKmsImplDevice *impl_device,
drmModeAtomicReq *req,
GError **error)
{
if (!disable_connectors (impl_device, req, error))
return FALSE;
if (!disable_planes (impl_device, req, error))
return FALSE;
if (!disable_crtcs (impl_device, req, error))
return FALSE;
return TRUE;
}
static MetaKmsFeedback *
meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
@ -953,19 +938,6 @@ meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device,
goto err;
}
if (meta_kms_update_is_power_save (update))
{
meta_topic (META_DEBUG_KMS,
"[atomic] Entering power save mode for %s",
meta_kms_impl_device_get_path (impl_device));
if (!process_power_save (impl_device, req, &error))
goto err;
commit_flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
goto commit;
}
if (!process_entries (impl_device,
update,
req,
@ -1017,7 +989,6 @@ meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device,
if (flags & META_KMS_UPDATE_FLAG_TEST_ONLY)
commit_flags |= DRM_MODE_ATOMIC_TEST_ONLY;
commit:
meta_topic (META_DEBUG_KMS,
"[atomic] Committing update %" G_GUINT64_FORMAT ", flags: %s",
meta_kms_update_get_sequence_number (update),
@ -1066,6 +1037,53 @@ err:
return meta_kms_feedback_new_failed (failed_planes, error);
}
static void
meta_kms_impl_device_atomic_disable (MetaKmsImplDevice *impl_device)
{
g_autoptr (GError) error = NULL;
drmModeAtomicReq *req;
int fd;
int ret;
meta_topic (META_DEBUG_KMS, "[atomic] Disabling '%s'",
meta_kms_impl_device_get_path (impl_device));
req = drmModeAtomicAlloc ();
if (!req)
{
g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Failed to create atomic transaction request: %s",
g_strerror (errno));
goto err;
}
if (!disable_connectors (impl_device, req, &error))
goto err;
if (!disable_planes (impl_device, req, &error))
goto err;
if (!disable_crtcs (impl_device, req, &error))
goto err;
meta_topic (META_DEBUG_KMS, "[atomic] Committing disable-device transaction");
fd = meta_kms_impl_device_get_fd (impl_device);
ret = drmModeAtomicCommit (fd, req, DRM_MODE_ATOMIC_ALLOW_MODESET, impl_device);
drmModeAtomicFree (req);
if (ret < 0)
{
g_set_error (&error, G_IO_ERROR, g_io_error_from_errno (-ret),
"drmModeAtomicCommit: %s", g_strerror (-ret));
goto err;
}
return;
err:
g_warning ("[atomic] Failed to disable device '%s': %s",
meta_kms_impl_device_get_path (impl_device),
error->message);
}
static void
meta_kms_impl_device_atomic_handle_page_flip_callback (MetaKmsImplDevice *impl_device,
MetaKmsPageFlipData *page_flip_data)
@ -1246,6 +1264,8 @@ meta_kms_impl_device_atomic_class_init (MetaKmsImplDeviceAtomicClass *klass)
meta_kms_impl_device_atomic_setup_drm_event_context;
impl_device_class->process_update =
meta_kms_impl_device_atomic_process_update;
impl_device_class->disable =
meta_kms_impl_device_atomic_disable;
impl_device_class->handle_page_flip_callback =
meta_kms_impl_device_atomic_handle_page_flip_callback;
impl_device_class->discard_pending_page_flips =

View File

@ -180,32 +180,6 @@ set_connector_property (MetaKmsImplDevice *impl_device,
return TRUE;
}
static gboolean
process_power_save (MetaKmsImplDevice *impl_device,
GError **error)
{
GList *l;
for (l = meta_kms_impl_device_peek_connectors (impl_device); l; l = l->next)
{
MetaKmsConnector *connector = l->data;
meta_topic (META_DEBUG_KMS,
"[simple] Setting DPMS of connector %u (%s) to OFF",
meta_kms_connector_get_id (connector),
meta_kms_impl_device_get_path (impl_device));
if (!set_connector_property (impl_device,
connector,
META_KMS_CONNECTOR_PROP_DPMS,
DRM_MODE_DPMS_OFF,
error))
return FALSE;
}
return TRUE;
}
static gboolean
process_connector_update (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
@ -1508,13 +1482,6 @@ meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device,
if (flags & META_KMS_UPDATE_FLAG_TEST_ONLY)
return perform_update_test (impl_device, update);
if (meta_kms_update_is_power_save (update))
{
if (!process_power_save (impl_device, &error))
goto err;
goto out;
}
if (!process_entries (impl_device,
update,
meta_kms_update_get_mode_sets (update),
@ -1543,13 +1510,54 @@ meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device,
&error))
goto err;
out:
return meta_kms_feedback_new_passed (failed_planes);
err:
return meta_kms_feedback_new_failed (failed_planes, error);
}
static gboolean
set_dpms_to_off (MetaKmsImplDevice *impl_device,
GError **error)
{
GList *l;
for (l = meta_kms_impl_device_peek_connectors (impl_device); l; l = l->next)
{
MetaKmsConnector *connector = l->data;
meta_topic (META_DEBUG_KMS,
"[simple] Setting DPMS of connector %u (%s) to OFF",
meta_kms_connector_get_id (connector),
meta_kms_impl_device_get_path (impl_device));
if (!set_connector_property (impl_device,
connector,
META_KMS_CONNECTOR_PROP_DPMS,
DRM_MODE_DPMS_OFF,
error))
return FALSE;
}
return TRUE;
}
static void
meta_kms_impl_device_simple_disable (MetaKmsImplDevice *impl_device)
{
g_autoptr (GError) error = NULL;
meta_topic (META_DEBUG_KMS, "[simple] Disabling '%s'",
meta_kms_impl_device_get_path (impl_device));
if (!set_dpms_to_off (impl_device, &error))
{
g_warning ("Failed to set DPMS to off on device '%s': %s",
meta_kms_impl_device_get_path (impl_device),
error->message);
}
}
static void
flush_postponed_page_flip_datas (MetaKmsImplDeviceSimple *impl_device_simple)
{
@ -1778,6 +1786,8 @@ meta_kms_impl_device_simple_class_init (MetaKmsImplDeviceSimpleClass *klass)
meta_kms_impl_device_simple_setup_drm_event_context;
impl_device_class->process_update =
meta_kms_impl_device_simple_process_update;
impl_device_class->disable =
meta_kms_impl_device_simple_disable;
impl_device_class->handle_page_flip_callback =
meta_kms_impl_device_simple_handle_page_flip_callback;
impl_device_class->discard_pending_page_flips =

View File

@ -823,6 +823,23 @@ meta_kms_impl_device_process_update (MetaKmsImplDevice *impl_device,
return feedback;
}
void
meta_kms_impl_device_disable (MetaKmsImplDevice *impl_device)
{
MetaKmsImplDevicePrivate *priv =
meta_kms_impl_device_get_instance_private (impl_device);
MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device);
if (!priv->device_file)
return;
meta_kms_impl_device_hold_fd (impl_device);
klass->disable (impl_device);
g_list_foreach (priv->crtcs, (GFunc) meta_kms_crtc_disable, NULL);
g_list_foreach (priv->connectors, (GFunc) meta_kms_connector_disable, NULL);
meta_kms_impl_device_unhold_fd (impl_device);
}
void
meta_kms_impl_device_handle_page_flip_callback (MetaKmsImplDevice *impl_device,
MetaKmsPageFlipData *page_flip_data)

View File

@ -75,6 +75,7 @@ struct _MetaKmsImplDeviceClass
MetaKmsFeedback * (* process_update) (MetaKmsImplDevice *impl_device,
MetaKmsUpdate *update,
MetaKmsUpdateFlag flags);
void (* disable) (MetaKmsImplDevice *impl_device);
void (* handle_page_flip_callback) (MetaKmsImplDevice *impl_device,
MetaKmsPageFlipData *page_flip_data);
void (* discard_pending_page_flips) (MetaKmsImplDevice *impl_device);
@ -124,6 +125,8 @@ const char * meta_kms_impl_device_get_path (MetaKmsImplDevice *impl_device);
gboolean meta_kms_impl_device_dispatch (MetaKmsImplDevice *impl_device,
GError **error);
void meta_kms_impl_device_disable (MetaKmsImplDevice *impl_device);
drmModePropertyPtr meta_kms_impl_device_find_property (MetaKmsImplDevice *impl_device,
drmModeObjectProperties *props,
const char *prop_name,

View File

@ -160,9 +160,6 @@ GList * meta_kms_update_get_connector_updates (MetaKmsUpdate *update);
META_EXPORT_TEST
GList * meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update);
META_EXPORT_TEST
gboolean meta_kms_update_is_power_save (MetaKmsUpdate *update);
MetaKmsCustomPageFlip * meta_kms_update_take_custom_page_flip_func (MetaKmsUpdate *update);
void meta_kms_update_drop_plane_assignment (MetaKmsUpdate *update,

View File

@ -35,8 +35,6 @@ struct _MetaKmsUpdate
gboolean is_locked;
uint64_t sequence_number;
gboolean power_save;
GList *mode_sets;
GList *plane_assignments;
GList *connector_updates;
@ -214,7 +212,6 @@ meta_kms_update_assign_plane (MetaKmsUpdate *update,
g_assert (!meta_kms_update_is_locked (update));
g_assert (meta_kms_crtc_get_device (crtc) == update->device);
g_assert (!update->power_save);
g_assert (meta_kms_plane_get_device (plane) == update->device);
g_assert (meta_kms_plane_get_plane_type (plane) !=
META_KMS_PLANE_TYPE_PRIMARY ||
@ -253,7 +250,6 @@ meta_kms_update_unassign_plane (MetaKmsUpdate *update,
g_assert (!meta_kms_update_is_locked (update));
g_assert (meta_kms_crtc_get_device (crtc) == update->device);
g_assert (meta_kms_plane_get_device (plane) == update->device);
g_assert (!update->power_save);
plane_assignment = g_new0 (MetaKmsPlaneAssignment, 1);
*plane_assignment = (MetaKmsPlaneAssignment) {
@ -279,7 +275,6 @@ meta_kms_update_mode_set (MetaKmsUpdate *update,
g_assert (!meta_kms_update_is_locked (update));
g_assert (meta_kms_crtc_get_device (crtc) == update->device);
g_assert (!update->power_save);
mode_set = g_new0 (MetaKmsModeSet, 1);
*mode_set = (MetaKmsModeSet) {
@ -325,7 +320,6 @@ meta_kms_update_set_underscanning (MetaKmsUpdate *update,
g_assert (!meta_kms_update_is_locked (update));
g_assert (meta_kms_connector_get_device (connector) == update->device);
g_assert (!update->power_save);
connector_update = ensure_connector_update (update, connector);
connector_update->underscanning.has_update = TRUE;
@ -342,7 +336,6 @@ meta_kms_update_unset_underscanning (MetaKmsUpdate *update,
g_assert (!meta_kms_update_is_locked (update));
g_assert (meta_kms_connector_get_device (connector) == update->device);
g_assert (!update->power_save);
connector_update = ensure_connector_update (update, connector);
connector_update->underscanning.has_update = TRUE;
@ -357,25 +350,12 @@ meta_kms_update_set_privacy_screen (MetaKmsUpdate *update,
MetaKmsConnectorUpdate *connector_update;
g_assert (meta_kms_connector_get_device (connector) == update->device);
g_assert (!update->power_save);
connector_update = ensure_connector_update (update, connector);
connector_update->privacy_screen.has_update = TRUE;
connector_update->privacy_screen.is_enabled = enabled;
}
void
meta_kms_update_set_power_save (MetaKmsUpdate *update)
{
g_assert (!meta_kms_update_is_locked (update));
g_assert (!update->mode_sets);
g_assert (!update->plane_assignments);
g_assert (!update->connector_updates);
g_assert (!update->crtc_gammas);
update->power_save = TRUE;
}
void
meta_kms_crtc_gamma_free (MetaKmsCrtcGamma *gamma)
{
@ -418,7 +398,6 @@ meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update,
g_assert (!meta_kms_update_is_locked (update));
g_assert (meta_kms_crtc_get_device (crtc) == update->device);
g_assert (!update->power_save);
gamma = meta_kms_crtc_gamma_new (crtc, size, red, green, blue);
@ -481,7 +460,6 @@ meta_kms_update_set_custom_page_flip (MetaKmsUpdate *update,
MetaKmsCustomPageFlip *custom_page_flip;
g_assert (!meta_kms_update_is_locked (update));
g_assert (!update->power_save);
custom_page_flip = g_new0 (MetaKmsCustomPageFlip, 1);
custom_page_flip->func = func;
@ -663,12 +641,6 @@ meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update)
return update->crtc_gammas;
}
gboolean
meta_kms_update_is_power_save (MetaKmsUpdate *update)
{
return update->power_save;
}
void
meta_kms_update_lock (MetaKmsUpdate *update)
{

View File

@ -52,8 +52,6 @@
#include "backends/native/meta-crtc-kms.h"
#include "backends/native/meta-gpu-kms.h"
#include "backends/native/meta-kms-device.h"
#include "backends/native/meta-kms-types.h"
#include "backends/native/meta-kms-update.h"
#include "backends/native/meta-kms.h"
#include "backends/native/meta-launcher.h"
#include "backends/native/meta-output-kms.h"
@ -150,8 +148,6 @@ meta_monitor_manager_native_set_power_save_mode (MetaMonitorManager *manager,
MetaPowerSave mode)
{
MetaBackend *backend = meta_monitor_manager_get_backend (manager);
MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
MetaKms *kms = meta_backend_native_get_kms (backend_native);
GList *l;
for (l = meta_backend_get_gpus (backend); l; l = l->next)
@ -172,24 +168,7 @@ meta_monitor_manager_native_set_power_save_mode (MetaMonitorManager *manager,
case META_POWER_SAVE_SUSPEND:
case META_POWER_SAVE_OFF:
{
MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
MetaKmsUpdate *kms_update;
MetaKmsUpdateFlag flags;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
kms_update = meta_kms_ensure_pending_update (kms, kms_device);
meta_kms_update_set_power_save (kms_update);
flags = META_KMS_UPDATE_FLAG_NONE;
kms_feedback = meta_kms_post_pending_update_sync (kms,
kms_device,
flags);
if (meta_kms_feedback_get_result (kms_feedback) !=
META_KMS_FEEDBACK_PASSED)
{
g_warning ("Failed to enter power saving mode: %s",
meta_kms_feedback_get_error (kms_feedback)->message);
}
meta_kms_device_disable (meta_gpu_kms_get_kms_device (gpu_kms));
break;
}
}

View File

@ -369,11 +369,7 @@ meta_test_kms_device_power_save (void)
* Enable power saving mode.
*/
update = meta_kms_update_new (device);
meta_kms_update_set_power_save (update);
meta_kms_device_process_update_sync (device, update,
META_KMS_UPDATE_FLAG_NONE);
meta_kms_update_free (update);
meta_kms_device_disable (device);
g_assert_false (meta_kms_crtc_is_active (crtc));
crtc_state = meta_kms_crtc_get_current_state (crtc);

View File

@ -44,7 +44,6 @@ meta_test_kms_update_sanity (void)
update = meta_kms_update_new (device);
g_assert (meta_kms_update_get_device (update) == device);
g_assert_false (meta_kms_update_is_locked (update));
g_assert_false (meta_kms_update_is_power_save (update));
g_assert_null (meta_kms_update_get_primary_plane_assignment (update, crtc));
g_assert_null (meta_kms_update_get_plane_assignments (update));
g_assert_null (meta_kms_update_get_mode_sets (update));