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:

committed by
Aleksander Morgado

parent
af44e8c1d8
commit
eeba2ff32b
@@ -102,6 +102,7 @@
|
|||||||
* @MM_CORE_ERROR_RETRY: Operation cannot yet be performed, retry later.
|
* @MM_CORE_ERROR_RETRY: Operation cannot yet be performed, retry later.
|
||||||
* @MM_CORE_ERROR_EXISTS: Item already exists.
|
* @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_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.
|
* 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_RETRY = 12, /*< nick=Retry >*/
|
||||||
MM_CORE_ERROR_EXISTS = 13, /*< nick=Exists >*/
|
MM_CORE_ERROR_EXISTS = 13, /*< nick=Exists >*/
|
||||||
MM_CORE_ERROR_WRONG_SIM_STATE = 14, /*< nick=WrongSimState >*/
|
MM_CORE_ERROR_WRONG_SIM_STATE = 14, /*< nick=WrongSimState >*/
|
||||||
|
MM_CORE_ERROR_RESET_AND_RETRY = 15, /*< nick=ResetRetry >*/
|
||||||
} MMCoreError;
|
} MMCoreError;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1585,10 +1585,13 @@ unlock_required_subscriber_ready_state_ready (MbimDevice *device,
|
|||||||
g_autoptr(MbimMessage) response = NULL;
|
g_autoptr(MbimMessage) response = NULL;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
MbimSubscriberReadyState ready_state = MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED;
|
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);
|
ctx = g_task_get_task_data (task);
|
||||||
self = g_task_get_source_object (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 */
|
/* reset to the default if any error happens */
|
||||||
self->priv->enabled_cache.last_ready_state = MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED;
|
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
|
else
|
||||||
g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
|
g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
|
||||||
"Error waiting for SIM to get initialized");
|
"Error waiting for SIM to get initialized");
|
||||||
} else
|
} else {
|
||||||
g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_RETRY,
|
/* 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)");
|
"SIM not ready yet (retry)");
|
||||||
|
}
|
||||||
g_object_unref (task);
|
g_object_unref (task);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -604,6 +604,12 @@ load_unlock_required_ready (MMIfaceModem *self,
|
|||||||
return;
|
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 */
|
/* For the remaining ones, retry if possible */
|
||||||
if (ctx->retries < ctx->max_retries) {
|
if (ctx->retries < ctx->max_retries) {
|
||||||
ctx->retries++;
|
ctx->retries++;
|
||||||
|
Reference in New Issue
Block a user