diff options
author | Nagi Marupaka <nmarupaka@google.com> | 2023-05-11 03:30:26 +0000 |
---|---|---|
committer | Aleksander Morgado <aleksandermj@chromium.org> | 2023-05-12 11:46:17 +0000 |
commit | eeba2ff32b83f96a2f8889962689b47870f6f8a6 (patch) | |
tree | 4601192f1349dbe333b8bc1b94d326fdbb0da041 | |
parent | af44e8c1d8abe7f3f913dec7fa385d1dcbbb676b (diff) | |
download | ModemManager-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.h | 2 | ||||
-rw-r--r-- | src/mm-broadband-modem-mbim.c | 19 | ||||
-rw-r--r-- | src/mm-iface-modem.c | 6 |
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++; |