From f5acb7ce85fec0c6cf1d284c125008b961f7a56e Mon Sep 17 00:00:00 2001 From: Dylan Van Assche Date: Sat, 13 Mar 2021 19:28:19 +0100 Subject: [PATCH 13/39] iface-modem-3gpp: synchronize state when resuming On resume, refresh the EPS bearers and 3GPP registration as the registration and bearers may expired during suspend. --- src/mm-broadband-modem.c | 31 +++++++ src/mm-iface-modem-3gpp.c | 177 ++++++++++++++++++++++++++++++++++++++ src/mm-iface-modem-3gpp.h | 12 +++ 3 files changed, 220 insertions(+) diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 91e023b8..05d72875 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -11343,6 +11343,7 @@ enable (MMBaseModem *self, typedef enum { SYNCING_STEP_FIRST, + SYNCING_STEP_IFACE_3GPP, SYNCING_STEP_IFACE_TIME, SYNCING_STEP_LAST, } SyncingStep; @@ -11379,6 +11380,24 @@ iface_modem_time_sync_ready (MMIfaceModemTime *self, syncing_step (task); } +static void +iface_modem_3gpp_sync_ready (MMBroadbandModem *self, + GAsyncResult *res, + GTask *task) +{ + SyncingContext *ctx; + g_autoptr(GError) error = NULL; + + ctx = g_task_get_task_data (task); + + if (!mm_iface_modem_3gpp_sync_finish (MM_IFACE_MODEM_3GPP (self), res, &error)) + mm_obj_warn (self, "3GPP interface synchronization failed: %s", error->message); + + /* Go on to next step */ + ctx->step++; + syncing_step (task); +} + static void syncing_step (GTask *task) { @@ -11393,6 +11412,18 @@ syncing_step (GTask *task) ctx->step++; /* fall through */ + case SYNCING_STEP_IFACE_3GPP: + /* + * Start interface 3GPP synchronization. + * We hardly depend on the registration and bearer status, + * therefore we cannot continue with the other steps until + * this one is finished. + */ + mm_obj_info (self, "resume synchronization state (%d/%d): 3GPP interface sync", + ctx->step, SYNCING_STEP_LAST); + mm_iface_modem_3gpp_sync (MM_IFACE_MODEM_3GPP (self), (GAsyncReadyCallback)iface_modem_3gpp_sync_ready, task); + return; + case SYNCING_STEP_IFACE_TIME: /* * Synchronize asynchronously the Time interface. diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c index 93899355..c435da87 100644 --- a/src/mm-iface-modem-3gpp.c +++ b/src/mm-iface-modem-3gpp.c @@ -2341,6 +2341,183 @@ mm_iface_modem_3gpp_enable (MMIfaceModem3gpp *self, /*****************************************************************************/ +#if defined WITH_SYSTEMD_SUSPEND_RESUME + +typedef struct _SyncingContext SyncingContext; +static void interface_syncing_step (GTask *task); + +typedef enum { + SYNCING_STEP_FIRST, + SYNCING_STEP_REFRESH_3GPP_REGISTRATION, + SYNCING_STEP_REFRESH_EPS_BEARER, + SYNCING_STEP_LAST +} SyncingStep; + +struct _SyncingContext { + SyncingStep step; +}; + +gboolean +mm_iface_modem_3gpp_sync_finish (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +sync_eps_bearer_ready (MMIfaceModem3gpp *self, + GAsyncResult *res, + GTask *task) +{ + MMBearerProperties *properties; + SyncingContext *ctx; + g_autoptr (GError) error = NULL; + + mm_obj_dbg (self, "EPS bearer sync ready"); + ctx = g_task_get_task_data (task); + + properties = MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_initial_eps_bearer_finish (self, res, &error); + if (!properties) { + mm_obj_dbg (self, "couldn't refresh EPS bearer properties: %s", error->message); + } else { + mm_iface_modem_3gpp_update_initial_eps_bearer (self, properties); + g_object_unref (properties); + } + + /* Go on to next step */ + ctx->step++; + interface_syncing_step (task); +} + +static void +sync_eps_bearer (MMIfaceModem3gpp *self, + GAsyncReadyCallback callback, + GTask *task) +{ + SyncingContext *ctx; + gboolean eps_supported = FALSE; + + g_object_get (self, + MM_IFACE_MODEM_3GPP_EPS_NETWORK_SUPPORTED, &eps_supported, + NULL); + + /* Refresh EPS bearer if supported */ + if (eps_supported && + MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_initial_eps_bearer && + MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_initial_eps_bearer_finish) { + MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_initial_eps_bearer ( + self, + callback, + task); + return; + } + + /* If EPS is unsupported, just go to the next step */ + ctx = g_task_get_task_data (task); + ctx->step++; + interface_syncing_step (task); +} + +static void +sync_registration_ready (MMIfaceModem3gpp *self, + GAsyncResult *res, + GTask *task) +{ + SyncingContext *ctx; + g_autoptr (GError) error = NULL; + + ctx = g_task_get_task_data (task); + + mm_iface_modem_3gpp_run_registration_checks_finish (self, res, &error); + if (error) { + mm_obj_dbg (self, "Synchronizing 3GPP registration failed: %s", error->message); + g_error_free (error); + } + + /* Go on to next step */ + ctx->step++; + interface_syncing_step(task); +} + +static void +interface_syncing_step (GTask *task) +{ + MMIfaceModem3gpp *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_REFRESH_3GPP_REGISTRATION: + /* + * Refresh registration info to verify that the modem is still registered. + * Wait until registration checks are complete before going to the next step. + */ + mm_iface_modem_3gpp_run_registration_checks ( + self, + (GAsyncReadyCallback)sync_registration_ready, + task); + return; + + case SYNCING_STEP_REFRESH_EPS_BEARER: + /* + * Refresh EPS bearer and wait until complete. + * We want to make sure that the modem is fully enabled again + * when we refresh the mobile data connection bearers. + */ + sync_eps_bearer ( + self, + (GAsyncReadyCallback)sync_eps_bearer_ready, + task); + return; + + case 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 (); +} + +void +mm_iface_modem_3gpp_sync (MMIfaceModem3gpp *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 (self, NULL, callback, user_data); + g_task_set_task_data (task, ctx, (GDestroyNotify)g_free); + interface_syncing_step (task); +} + +#endif + +/*****************************************************************************/ + typedef struct _InitializationContext InitializationContext; static void interface_initialization_step (GTask *task); diff --git a/src/mm-iface-modem-3gpp.h b/src/mm-iface-modem-3gpp.h index 258e5c10..027bef0f 100644 --- a/src/mm-iface-modem-3gpp.h +++ b/src/mm-iface-modem-3gpp.h @@ -265,6 +265,18 @@ gboolean mm_iface_modem_3gpp_disable_finish (MMIfaceModem3gpp *self, GAsyncResult *res, GError **error); +#if defined WITH_SYSTEMD_SUSPEND_RESUME + +/* Sync 3GPP interface (async) */ +void mm_iface_modem_3gpp_sync (MMIfaceModem3gpp *self, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_iface_modem_3gpp_sync_finish (MMIfaceModem3gpp *self, + GAsyncResult *res, + GError **error); + +#endif + /* Shutdown Modem 3GPP interface */ void mm_iface_modem_3gpp_shutdown (MMIfaceModem3gpp *self); -- 2.31.1