From 9cc2cb3e96b8282fdc31725bcb397eceb7f4a53a Mon Sep 17 00:00:00 2001 From: Tongze Wang Date: Thu, 18 Jun 2026 23:31:40 +0800 Subject: [PATCH] [spinel] improve RCP crash dump request logic (#13150) This commit updates the RCP crash dump request logic to provide better debug information while ensuring the recovery process is not interrupted: - `RadioSpinel::HandleRcpUnexpectedReset` now explicitly clears `mWaitingTid` and requests a crash dump if RCP restoration is disabled before proceeding with the abort / exit logic. If RCP restoration is enabled, request for crash dump will be deferred to `RecoverFromRcpFailure`, before resetting the coprocessor. - Updates crash dump requests to use `IgnoreReturnValue` instead. Failing to retrieve a crash dump is not a fatal error and should not halt the initialization or recovery process. --- src/lib/spinel/radio_spinel.cpp | 48 +++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/src/lib/spinel/radio_spinel.cpp b/src/lib/spinel/radio_spinel.cpp index 75bc730e1..8c09a97b7 100644 --- a/src/lib/spinel/radio_spinel.cpp +++ b/src/lib/spinel/radio_spinel.cpp @@ -157,7 +157,7 @@ void RadioSpinel::Init(bool aSkipRcpVersionCheck, if (sSupportsLogCrashDump) { LogDebg("RCP supports crash dump logging. Requesting crash dump."); - SuccessOrExit(error = Set(SPINEL_PROP_RCP_LOG_CRASH_DUMP, nullptr)); + IgnoreReturnValue(Set(SPINEL_PROP_RCP_LOG_CRASH_DUMP, nullptr)); } if (!aSkipRcpVersionCheck) @@ -1328,14 +1328,17 @@ otError RadioSpinel::Set(spinel_prop_key_t aKey, const char *aFormat, ...) #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0 do { - RecoverFromRcpFailure(); + if (aKey != SPINEL_PROP_RCP_LOG_CRASH_DUMP) + { + RecoverFromRcpFailure(); + } #endif va_start(mPropertyArgs, aFormat); error = RequestWithExpectedCommandV(SPINEL_CMD_PROP_VALUE_IS, SPINEL_CMD_PROP_VALUE_SET, aKey, aFormat, mPropertyArgs); va_end(mPropertyArgs); #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0 - } while (mRcpFailure != kRcpFailureNone); + } while (aKey != SPINEL_PROP_RCP_LOG_CRASH_DUMP && mRcpFailure != kRcpFailureNone); #endif return error; @@ -1399,12 +1402,19 @@ otError RadioSpinel::WaitResponse(bool aHandleRcpTimeout) if ((end <= now) || (GetSpinelDriver().GetSpinelInterface()->WaitForFrame(end - now) != OT_ERROR_NONE)) { LogWarn("Wait for response timeout"); - if (aHandleRcpTimeout) + // Skip RCP timeout handling for the non-essential crash dump property + if (aHandleRcpTimeout && mWaitingKey != SPINEL_PROP_RCP_LOG_CRASH_DUMP) { HandleRcpTimeout(); } ExitNow(mError = OT_ERROR_RESPONSE_TIMEOUT); } +#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0 + if (mRcpFailure != kRcpFailureNone) + { + ExitNow(mError = OT_ERROR_RESPONSE_TIMEOUT); + } +#endif } while (mWaitingTid); LogIfFail("Error waiting response", mError); @@ -1412,6 +1422,11 @@ otError RadioSpinel::WaitResponse(bool aHandleRcpTimeout) mWaitingKey = SPINEL_PROP_LAST_STATUS; exit: + if (mError != OT_ERROR_NONE && mWaitingTid != 0) + { + FreeTid(mWaitingTid); + mWaitingTid = 0; + } return mError; } @@ -1991,11 +2006,20 @@ void RadioSpinel::HandleRcpUnexpectedReset(spinel_status_t aStatus) #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0 mRcpFailure = kRcpFailureUnexpectedReset; -#elif OPENTHREAD_SPINEL_CONFIG_ABORT_ON_UNEXPECTED_RCP_RESET_ENABLE +#else + if (sSupportsLogCrashDump) + { + mWaitingTid = 0; + LogDebg("RCP supports crash dump logging. Requesting crash dump."); + IgnoreReturnValue(Set(SPINEL_PROP_RCP_LOG_CRASH_DUMP, nullptr)); + } + +#if OPENTHREAD_SPINEL_CONFIG_ABORT_ON_UNEXPECTED_RCP_RESET_ENABLE abort(); #else DieNow(OT_EXIT_RADIO_SPINEL_RESET); #endif +#endif } void RadioSpinel::HandleRcpTimeout(void) @@ -2044,6 +2068,14 @@ void RadioSpinel::RecoverFromRcpFailure(void) DieNow(OT_EXIT_FAILURE); } + if (sSupportsLogCrashDump) + { + mWaitingTid = 0; + LogDebg("RCP supports crash dump logging. Requesting crash dump."); + IgnoreReturnValue(Set(SPINEL_PROP_RCP_LOG_CRASH_DUMP, nullptr)); + mRcpFailure = kRcpFailureNone; + } + LogWarn("Trying to recover (%d/%d)", mRcpFailureCount, kMaxFailureCount); mState = kStateDisabled; @@ -2106,12 +2138,6 @@ void RadioSpinel::RecoverFromRcpFailure(void) --mRcpFailureCount; - if (sSupportsLogCrashDump) - { - LogDebg("RCP supports crash dump logging. Requesting crash dump."); - SuccessOrDie(Set(SPINEL_PROP_RCP_LOG_CRASH_DUMP, nullptr)); - } - LogNote("RCP recovery is done"); exit: