aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksandermj@chromium.org>2024-01-08 11:20:53 +0000
committerAleksander Morgado <aleksandermj@chromium.org>2024-01-26 12:27:44 +0000
commitcddf31bf7af60919ea220f499bb118af3503082b (patch)
tree2b99887778b093803c994f7bc0bbeb720097e382 /src
parentd30975782c96732a54ca13a05065959171e1d095 (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.c33
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);
}