diff options
author | Dylan Van Assche <me@dylanvanassche.be> | 2021-05-01 15:50:47 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2021-05-26 13:14:52 +0000 |
commit | 38740e9d11a52f91e41349a62caf35f8e1a67f48 (patch) | |
tree | d1c1514d9cf98790a44e1e156ce71adc8922cd0b | |
parent | 940063419a1c2eb9f6e197d60b4c7cb42702de8d (diff) |
base-manager: add quick suspend/resume base
Quick suspend/resume infrastructure for
synchronizing the interfaces when resuming.
-rw-r--r-- | src/main.c | 14 | ||||
-rw-r--r-- | src/mm-base-manager.c | 48 | ||||
-rw-r--r-- | src/mm-base-manager.h | 4 | ||||
-rw-r--r-- | src/mm-base-modem.c | 25 | ||||
-rw-r--r-- | src/mm-base-modem.h | 17 | ||||
-rw-r--r-- | src/mm-broadband-modem.c | 81 | ||||
-rw-r--r-- | src/mm-context.c | 11 | ||||
-rw-r--r-- | src/mm-context.h | 1 |
8 files changed, 200 insertions, 1 deletions
@@ -72,6 +72,13 @@ resuming_cb (MMSleepMonitor *sleep_monitor) mm_base_manager_start (manager, FALSE); } +static void +resuming_quick_cb (MMSleepMonitor *sleep_monitor) +{ + mm_dbg ("syncing modem state (quick resuming)"); + mm_base_manager_sync (manager); +} + #endif static void @@ -191,7 +198,12 @@ main (int argc, char *argv[]) if (mm_context_get_test_no_suspend_resume()) mm_dbg ("Suspend/resume support disabled at runtime"); - else { + else if (mm_context_get_test_quick_suspend_resume()) { + mm_dbg ("Quick suspend/resume hooks enabled"); + sleep_monitor = mm_sleep_monitor_get (); + g_signal_connect (sleep_monitor, MM_SLEEP_MONITOR_RESUMING, G_CALLBACK (resuming_quick_cb), NULL); + } else { + mm_dbg ("Full suspend/resume hooks enabled"); sleep_monitor = mm_sleep_monitor_get (); g_signal_connect (sleep_monitor, MM_SLEEP_MONITOR_SLEEPING, G_CALLBACK (sleeping_cb), NULL); g_signal_connect (sleep_monitor, MM_SLEEP_MONITOR_RESUMING, G_CALLBACK (resuming_cb), NULL); diff --git a/src/mm-base-manager.c b/src/mm-base-manager.c index 24812932..e7df890a 100644 --- a/src/mm-base-manager.c +++ b/src/mm-base-manager.c @@ -52,6 +52,7 @@ #include "mm-plugin.h" #include "mm-filter.h" #include "mm-log-object.h" +#include "mm-base-modem.h" static void initable_iface_init (GInitableIface *iface); static void log_object_iface_init (MMLogObjectInterface *iface); @@ -724,6 +725,53 @@ mm_base_manager_num_modems (MMBaseManager *self) } /*****************************************************************************/ +/* Quick resume synchronization */ + +#if defined WITH_SYSTEMD_SUSPEND_RESUME + +gboolean mm_base_modem_sync_finish (MMBaseModem *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +mm_base_modem_sync_ready (MMBaseModem *self, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) error; + + mm_base_modem_sync_finish (self, res, &error); + if (error) { + mm_obj_warn (self, "synchronization failed"); + return; + } + mm_obj_info (self, "synchronization finished"); +} + +void +mm_base_manager_sync (MMBaseManager *self) +{ + GHashTableIter iter; + gpointer key, value; + + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_BASE_MANAGER (self)); + + /* Refresh each device */ + g_hash_table_iter_init (&iter, self->priv->devices); + while (g_hash_table_iter_next (&iter, &key, &value)) { + MMBaseModem *modem = mm_device_peek_modem (MM_DEVICE (value)); + /* We just want to start the synchronization, we don't need the result */ + mm_base_modem_sync (modem, (GAsyncReadyCallback)mm_base_modem_sync_ready, NULL); + } +} + +#endif + +/*****************************************************************************/ /* Set logging */ typedef struct { diff --git a/src/mm-base-manager.h b/src/mm-base-manager.h index d70fa08f..be51d0c0 100644 --- a/src/mm-base-manager.h +++ b/src/mm-base-manager.h @@ -66,6 +66,10 @@ void mm_base_manager_start (MMBaseManager *manager, void mm_base_manager_shutdown (MMBaseManager *manager, gboolean disable); +#if defined WITH_SYSTEMD_SUSPEND_RESUME +void mm_base_manager_sync (MMBaseManager *manager); +#endif + guint32 mm_base_manager_num_modems (MMBaseManager *manager); #endif /* MM_BASE_MANAGER_H */ diff --git a/src/mm-base-modem.c b/src/mm-base-modem.c index 06562af4..55752999 100644 --- a/src/mm-base-modem.c +++ b/src/mm-base-modem.c @@ -620,6 +620,31 @@ mm_base_modem_wait_link_port (MMBaseModem *self, /******************************************************************************/ +static void +mm_base_modem_sync_ready (MMBaseModem *self, + GAsyncResult *res) +{ + g_autoptr (GError) error = NULL; + + MM_BASE_MODEM_GET_CLASS (self)->sync_finish (self, res, &error); + if (error) { + mm_obj_warn (self, "synchronization failed"); + } +} + +void +mm_base_modem_sync (MMBaseModem *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_assert (MM_BASE_MODEM_GET_CLASS (self)->sync != NULL); + g_assert (MM_BASE_MODEM_GET_CLASS (self)->sync_finish != NULL); + + MM_BASE_MODEM_GET_CLASS (self)->sync (self, + (GAsyncReadyCallback) mm_base_modem_sync_ready, + NULL); +} + gboolean mm_base_modem_disable_finish (MMBaseModem *self, GAsyncResult *res, diff --git a/src/mm-base-modem.h b/src/mm-base-modem.h index 776e3c9c..6194eb93 100644 --- a/src/mm-base-modem.h +++ b/src/mm-base-modem.h @@ -108,6 +108,16 @@ struct _MMBaseModemClass { GAsyncResult *res, GError **error); + /* Modem synchronization. + * When resuming in quick suspend/resume mode, + * this method triggers a synchronization of all modem interfaces */ + void (* sync) (MMBaseModem *self, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (* sync_finish) (MMBaseModem *self, + GAsyncResult *res, + GError **error); + /* signals */ void (* link_port_grabbed) (MMBaseModem *self, MMPort *link_port); @@ -231,6 +241,13 @@ gboolean mm_base_modem_disable_finish (MMBaseModem *self, GAsyncResult *res, GError **error); +void mm_base_modem_sync (MMBaseModem *self, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_base_modem_sync_finish (MMBaseModem *self, + GAsyncResult *res, + GError **error); + void mm_base_modem_process_sim_event (MMBaseModem *self); #endif /* MM_BASE_MODEM_H */ diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index ee2adfc8..fa1f6125 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -11937,6 +11937,82 @@ enable (MMBaseModem *self, g_object_unref (task); } +/*****************************************************************************/ + +#if defined WITH_SYSTEMD_SUSPEND_RESUME + +typedef enum { + SYNCING_STEP_FIRST, + SYNCING_STEP_LAST, +} SyncingStep; + +typedef struct { + SyncingStep step; +} SyncingContext; + +static gboolean +synchronize_finish (MMBaseModem *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +syncing_step (GTask *task) +{ + MMBroadbandModem *self; + SyncingContext *ctx; + + /* Don't run new steps if we're cancelled */ + if (g_task_return_error_if_cancelled (task)) { + g_object_unref (task); + return; + } + + self = g_task_get_source_object (task); + ctx = g_task_get_task_data (task); + + switch (ctx->step) { + case SYNCING_STEP_FIRST: + ctx->step++; + /* fall through */ + + case SYNCING_STEP_LAST: + mm_obj_info (self, "resume synchronization state (%d/%d): all done", + ctx->step, SYNCING_STEP_LAST); + /* We are done without errors! */ + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + + default: + break; + } + + g_assert_not_reached (); +} + +/* 'sync' as function name conflicts with a declared function in unistd.h */ +static void +synchronize (MMBaseModem *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SyncingContext *ctx; + GTask *task; + + /* Create SyncingContext */ + ctx = g_new0 (SyncingContext, 1); + ctx->step = SYNCING_STEP_FIRST; + + /* Create sync steps task and execute it */ + task = g_task_new (MM_BROADBAND_MODEM (self), NULL, callback, user_data); + g_task_set_task_data (task, ctx, (GDestroyNotify)g_free); + syncing_step (task); +} + +#endif /*****************************************************************************/ @@ -13343,6 +13419,11 @@ mm_broadband_modem_class_init (MMBroadbandModemClass *klass) base_modem_class->disable = disable; base_modem_class->disable_finish = disable_finish; +#if defined WITH_SYSTEMD_SUSPEND_RESUME + base_modem_class->sync = synchronize; + base_modem_class->sync_finish = synchronize_finish; +#endif + klass->setup_ports = setup_ports; klass->initialization_started = initialization_started; klass->initialization_started_finish = initialization_started_finish; diff --git a/src/mm-context.c b/src/mm-context.c index 32590c55..ddc37a33 100644 --- a/src/mm-context.c +++ b/src/mm-context.c @@ -227,6 +227,7 @@ static gboolean test_no_udev; #endif #if defined WITH_SYSTEMD_SUSPEND_RESUME static gboolean test_no_suspend_resume; +static gboolean test_quick_suspend_resume; #endif #if defined WITH_QRTR static gboolean test_no_qrtr; @@ -261,6 +262,11 @@ static const GOptionEntry test_entries[] = { "Disable suspend/resume support at runtime even if available", NULL }, + { + "test-quick-suspend-resume", 0, 0, G_OPTION_ARG_NONE, &test_quick_suspend_resume, + "Enable quick suspend/resume support for modems which stay on during host suspension", + NULL + }, #endif #if defined WITH_QRTR { @@ -318,6 +324,11 @@ mm_context_get_test_no_suspend_resume (void) { return test_no_suspend_resume; } +gboolean +mm_context_get_test_quick_suspend_resume (void) +{ + return test_quick_suspend_resume; +} #endif #if defined WITH_QRTR diff --git a/src/mm-context.h b/src/mm-context.h index ea9df0cb..0e652ba3 100644 --- a/src/mm-context.h +++ b/src/mm-context.h @@ -51,6 +51,7 @@ gboolean mm_context_get_test_no_udev (void); #endif #if defined WITH_SYSTEMD_SUSPEND_RESUME gboolean mm_context_get_test_no_suspend_resume (void); +gboolean mm_context_get_test_quick_suspend_resume (void); #endif #if defined WITH_QRTR gboolean mm_context_get_test_no_qrtr (void); |