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.
This commit is contained in:
Nagi Marupaka
2023-05-11 03:30:26 +00:00
committed by Aleksander Morgado
parent af44e8c1d8
commit eeba2ff32b
3 changed files with 25 additions and 2 deletions

View File

@@ -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;
/**

View File

@@ -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;
}

View File

@@ -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++;