summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNagi Marupaka <nmarupaka@google.com>2023-05-11 03:30:26 +0000
committerAleksander Morgado <aleksandermj@chromium.org>2023-05-12 11:46:17 +0000
commiteeba2ff32b83f96a2f8889962689b47870f6f8a6 (patch)
tree4601192f1349dbe333b8bc1b94d326fdbb0da041
parentaf44e8c1d8abe7f3f913dec7fa385d1dcbbb676b (diff)
downloadModemManager-eeba2ff32b83f96a2f8889962689b47870f6f8a6.tar.gz
broadband-modem-mbim: account for race condition in quick hot swap case
On MBIM modems, when the SIM is ejected and re-inserted in a quick manner, the state machine logic encounters a race condition and eventually, the modem response for subscriber status is ignored. This change accounts for that state transition without erroring out. Fixes #672.
-rw-r--r--include/ModemManager-errors.h2
-rw-r--r--src/mm-broadband-modem-mbim.c19
-rw-r--r--src/mm-iface-modem.c6
3 files changed, 25 insertions, 2 deletions
diff --git a/include/ModemManager-errors.h b/include/ModemManager-errors.h
index 6d3315b54..43b239c5b 100644
--- a/include/ModemManager-errors.h
+++ b/include/ModemManager-errors.h
@@ -102,6 +102,7 @@
* @MM_CORE_ERROR_RETRY: Operation cannot yet be performed, retry later.
* @MM_CORE_ERROR_EXISTS: Item already exists.
* @MM_CORE_ERROR_WRONG_SIM_STATE: Operation cannot be executed in the current SIM state. Since 1.20.
+ * @MM_CORE_ERROR_RESET_AND_RETRY: Operation cannot yet be performed, reset the retry count and retry later. Since 1.22.
*
* Common errors that may be reported by ModemManager.
*
@@ -123,6 +124,7 @@ typedef enum { /*< underscore_name=mm_core_error >*/
MM_CORE_ERROR_RETRY = 12, /*< nick=Retry >*/
MM_CORE_ERROR_EXISTS = 13, /*< nick=Exists >*/
MM_CORE_ERROR_WRONG_SIM_STATE = 14, /*< nick=WrongSimState >*/
+ MM_CORE_ERROR_RESET_AND_RETRY = 15, /*< nick=ResetRetry >*/
} MMCoreError;
/**
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c
index 28cca816e..1150c7312 100644
--- a/src/mm-broadband-modem-mbim.c
+++ b/src/mm-broadband-modem-mbim.c
@@ -1585,10 +1585,13 @@ unlock_required_subscriber_ready_state_ready (MbimDevice *device,
g_autoptr(MbimMessage) response = NULL;
GError *error = NULL;
MbimSubscriberReadyState ready_state = MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED;
+ MbimSubscriberReadyState prev_ready_state = MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED;
ctx = g_task_get_task_data (task);
self = g_task_get_source_object (task);
+ /* hold on to the previous ready_state value to determine if the retry logic needs to be reset. */
+ prev_ready_state = self->priv->enabled_cache.last_ready_state;
/* reset to the default if any error happens */
self->priv->enabled_cache.last_ready_state = MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED;
@@ -1671,9 +1674,21 @@ unlock_required_subscriber_ready_state_ready (MbimDevice *device,
else
g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
"Error waiting for SIM to get initialized");
- } else
- g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_RETRY,
+ } else {
+ /* Start the retry process from the top if the SIM state changes from
+ * MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED to
+ * MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED
+ * This will address the race condition that occurs during rapid hotswap. */
+ gboolean retry_reset_needed = FALSE;
+
+ if (prev_ready_state == MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED &&
+ ready_state == MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED)
+ retry_reset_needed = TRUE;
+ g_task_return_new_error (task,
+ MM_CORE_ERROR,
+ retry_reset_needed ? MM_CORE_ERROR_RESET_AND_RETRY : MM_CORE_ERROR_RETRY,
"SIM not ready yet (retry)");
+ }
g_object_unref (task);
return;
}
diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c
index b30f710e9..12f262234 100644
--- a/src/mm-iface-modem.c
+++ b/src/mm-iface-modem.c
@@ -604,6 +604,12 @@ load_unlock_required_ready (MMIfaceModem *self,
return;
}
+ /* If the error indicates that retry logic needs to be reset... reset the retry count to 0 */
+ if (g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_RESET_AND_RETRY)) {
+ ctx->retries = 0;
+ mm_obj_info (self, "restarting unlock required check");
+ }
+
/* For the remaining ones, retry if possible */
if (ctx->retries < ctx->max_retries) {
ctx->retries++;