[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.
This commit is contained in:
Tongze Wang
2026-06-18 10:31:40 -05:00
committed by GitHub
parent 54323a2953
commit 9cc2cb3e96
+37 -11
View File
@@ -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: