diff options
author | Aleksander Morgado <aleksandermj@chromium.org> | 2024-01-08 11:20:53 +0000 |
---|---|---|
committer | Aleksander Morgado <aleksandermj@chromium.org> | 2024-01-26 12:27:44 +0000 |
commit | cddf31bf7af60919ea220f499bb118af3503082b (patch) | |
tree | 2b99887778b093803c994f7bc0bbeb720097e382 /src | |
parent | d30975782c96732a54ca13a05065959171e1d095 (diff) |
broadband-modem-qmi: don't complete the power update before receiving the response
When relying on the power update indications, we were completing the
operation as soon as the indication was received, regardless of
whether the request response was received or not.
Avoid doing that, and instead complete the operation only when both
indication and the response are received. This avoid misalignment in
the operation completion if a new one is scheduled just after the one
we have completed.
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-broadband-modem-qmi.c | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c index faf2522e..c9b8abdd 100644 --- a/src/mm-broadband-modem-qmi.c +++ b/src/mm-broadband-modem-qmi.c @@ -1987,6 +1987,8 @@ typedef struct { gboolean event_report_set; guint indication_id; guint timeout_id; + gboolean indication_received; + gboolean response_received; gboolean reload; GError *saved_error; } SetOperatingModeContext; @@ -2150,10 +2152,16 @@ dms_set_operating_mode_timeout_cb (MMBroadbandModemQmi *self) g_assert (self->priv->set_operating_mode_task); ctx = g_task_get_task_data (self->priv->set_operating_mode_task); - /* Save a timeout error, but also request to reload, in case the modem - * failed to send the indication even if it did update the power state */ - ctx->saved_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_TIMEOUT, "Power update operation timed out"); - ctx->reload = TRUE; + /* We may have received an indication but not the response to the request. In this case, + * complete with the results already set in the indication. */ + if (ctx->indication_received && !ctx->response_received) { + mm_obj_dbg (self, "Power update operation timed out, but result was already received"); + } else { + /* Save a timeout error, but also request to reload, in case the modem + * failed to send the indication even if it did update the power state */ + ctx->saved_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_TIMEOUT, "Power update operation timed out"); + ctx->reload = TRUE; + } set_operating_mode_complete (self); return G_SOURCE_REMOVE; @@ -2170,6 +2178,8 @@ power_event_report_indication_cb (QmiClientDms *client, g_assert (self->priv->set_operating_mode_task); ctx = g_task_get_task_data (self->priv->set_operating_mode_task); + ctx->indication_received = TRUE; + g_assert (!ctx->saved_error); if (!qmi_indication_dms_event_report_output_get_operating_mode (output, &state, NULL)) ctx->saved_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Invalid power indication received"); @@ -2182,7 +2192,9 @@ power_event_report_indication_cb (QmiClientDms *client, else mm_obj_dbg (self, "Power state successfully updated: '%s'", qmi_dms_operating_mode_get_string (state)); - set_operating_mode_complete (self); + /* The indication only completes the operation if it is received AFTER the response */ + if (ctx->response_received) + set_operating_mode_complete (self); } static void @@ -2195,11 +2207,12 @@ dms_set_operating_mode_ready (QmiClientDms *client, GError *error = NULL; SetOperatingModeContext *ctx; - /* We may have completed the operation already via indication */ + /* We may have completed the operation already as a timeout */ if (!self->priv->set_operating_mode_task) return; ctx = g_task_get_task_data (self->priv->set_operating_mode_task); + ctx->response_received = TRUE; output = qmi_client_dms_set_operating_mode_finish (client, res, &error); if (!output || !qmi_message_dms_set_operating_mode_output_get_result (output, &error)) { @@ -2227,25 +2240,27 @@ dms_set_operating_mode_ready (QmiClientDms *client, if (g_error_matches (error, QMI_CORE_ERROR, QMI_CORE_ERROR_UNSUPPORTED)) { mm_obj_dbg (self, "device doesn't support operating mode setting: ignoring power update"); g_clear_error (&error); + g_clear_error (&ctx->saved_error); set_operating_mode_complete (self); return; } - /* An error reported right away */ + /* An error reported right away, prefer it to the one received via indication, if any */ if (error) { + g_clear_error (&ctx->saved_error); ctx->saved_error = error; set_operating_mode_complete (self); return; } /* Request successful but indication not yet received */ - if (ctx->event_report_set) { + if (ctx->event_report_set && !ctx->indication_received) { g_assert (ctx->timeout_id); mm_obj_dbg (self, "operating mode request sent, waiting for power update indication"); return; } - /* Request successful and no indication needed */ + /* Request successful and no indication needed, or indication already received */ mm_obj_dbg (self, "operating mode request finished: no need to wait for indications"); set_operating_mode_complete (self); } |