Windows: Reset the Device on Initialization. (#1326)

* Reset the device on initialization.

* Explicitly break out of do {} while loop.
This commit is contained in:
Nick Banks
2017-02-17 08:54:08 -08:00
committed by Jonathan Hui
parent 827555139c
commit 303406bc3b
8 changed files with 85 additions and 46 deletions
+68 -2
View File
@@ -79,10 +79,17 @@ otLwfCmdInitialize(
{
pFilter->cmdTIDsInUse = 0;
pFilter->cmdNextTID = 1;
pFilter->cmdResetReason = kPlatResetReason_PowerOn;
NdisAllocateSpinLock(&pFilter->cmdLock);
InitializeListHead(&pFilter->cmdHandlers);
KeInitializeEvent(
&pFilter->cmdResetCompleteEvent,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
// Enable rundown protection
ExReInitializeRundownProtection(&pFilter->cmdRundown);
@@ -96,7 +103,7 @@ otLwfCmdInitialize(
}
// Query the interface type to make sure it is a Thread device
#if DBG
#ifdef COMMAND_INIT_RETRY
pFilter->cmdInitTryCount = 0;
while (pFilter->cmdInitTryCount < 10)
{
@@ -127,6 +134,13 @@ otLwfCmdInitialize(
break;
}
NtStatus = otLwfCmdResetDevice(pFilter, FALSE);
if (!NT_SUCCESS(NtStatus))
{
Status = NDIS_STATUS_FAILURE;
break;
}
} while (FALSE);
LogFuncExitNDIS(DRIVER_DEFAULT, Status);
@@ -214,7 +228,24 @@ otLwfCmdProcess(
// Get the transaction ID
if (SPINEL_HEADER_GET_TID(Header) == 0)
{
if (ExAcquireRundownProtection(&pFilter->ExternalRefs))
// Handle out of band last status locally
if (command == SPINEL_CMD_PROP_VALUE_IS && key == SPINEL_PROP_LAST_STATUS)
{
// Check if this is a reset
spinel_status_t status = SPINEL_STATUS_OK;
spinel_datatype_unpack(value_data_ptr, value_data_len, "i", &status);
if ((status >= SPINEL_STATUS_RESET__BEGIN) && (status <= SPINEL_STATUS_RESET__END))
{
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! was reset (status %d).", &pFilter->InterfaceGuid, status);
pFilter->cmdResetReason = status - SPINEL_STATUS_RESET__BEGIN;
KeSetEvent(&pFilter->cmdResetCompleteEvent, IO_NO_INCREMENT, FALSE);
// TODO - Should this be passed on to Thread or Tunnel logic?
NT_ASSERT(pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_UNINTIALIZED);
}
}
else if (ExAcquireRundownProtection(&pFilter->ExternalRefs))
{
// If this is a 'Value Is' command, process it for notification of state changes.
if (command == SPINEL_CMD_PROP_VALUE_IS)
@@ -521,6 +552,41 @@ exit:
return status;
}
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
otLwfCmdResetDevice(
_In_ PMS_FILTER pFilter,
_In_ BOOLEAN fAsync
)
{
LogFuncEntry(DRIVER_DEFAULT);
KeResetEvent(&pFilter->cmdResetCompleteEvent);
NTSTATUS status = otLwfCmdEncodeAndSendAsync(pFilter, SPINEL_CMD_RESET, 0, 0, 0, NULL, NULL);
if (!NT_SUCCESS(status))
{
LogError(DRIVER_DEFAULT, "Failed to send SPINEL_CMD_RESET, %!STATUS!", status);
}
else if (!fAsync)
{
// Create the relative (negative) time to wait for 5 seconds
LARGE_INTEGER Timeout;
Timeout.QuadPart = -5000 * 10000;
status = KeWaitForSingleObject(&pFilter->cmdResetCompleteEvent, Executive, KernelMode, FALSE, &Timeout);
if (status != STATUS_SUCCESS)
{
LogError(DRIVER_DEFAULT, "Failed waiting for reset complete, %!STATUS!", status);
status = STATUS_DEVICE_BUSY;
}
}
LogFuncExitNT(DRIVER_DEFAULT, status);
return status;
}
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
otLwfCmdSendAsyncV(
+7
View File
@@ -51,6 +51,13 @@ otLwfCmdUninitialize(
_In_ PMS_FILTER pFilter
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
otLwfCmdResetDevice(
_In_ PMS_FILTER pFilter,
_In_ BOOLEAN fAsync
);
//
// Receive Spinel Encoded Command
//
+1 -1
View File
@@ -117,7 +117,7 @@ Arguments:
spinel_tid_t tid = (spinel_tid_t)(ULONG_PTR)NetBuffer->ProtocolReserved[1];
if (tid != 0)
{
#if DBG
#ifdef COMMAND_INIT_RETRY
NT_ASSERT(pFilter->cmdInitTryCount < 9 || NBL->Status != NDIS_STATUS_PAUSED);
#endif
otLwfCmdCancel(pFilter, NDIS_TEST_SEND_COMPLETE_AT_DISPATCH_LEVEL(SendCompleteFlags), tid);
+3 -1
View File
@@ -160,9 +160,11 @@ typedef struct _MS_FILTER
USHORT cmdTIDsInUse;
spinel_tid_t cmdNextTID;
NDIS_HANDLE cmdNblPool;
#if DBG
#ifdef COMMAND_INIT_RETRY
ULONG cmdInitTryCount;
#endif
otPlatResetReason cmdResetReason;
KEVENT cmdResetCompleteEvent;
//
// Device Capabilities / State
+1
View File
@@ -109,6 +109,7 @@ typedef struct UDPHeader
//#define DEBUG_ALLOC
#define LOG_BUFFERS
//#define FORCE_SYNCHRONOUS_RECEIVE
#define COMMAND_INIT_RETRY
#include "driver.h"
#include "device.h"
+3 -18
View File
@@ -56,26 +56,11 @@ otPlatReset(
{
NT_ASSERT(otCtx);
PMS_FILTER pFilter = otCtxToFilter(otCtx);
NTSTATUS status;
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! resetting...", &pFilter->InterfaceGuid);
// Indicate to the miniport
status =
otLwfCmdSendAsync(
pFilter,
NULL,
NULL,
NULL,
SPINEL_CMD_RESET,
0,
0,
NULL
);
if (!NT_SUCCESS(status))
{
LogError(DRIVER_DEFAULT, "Send SPINEL_CMD_RESET failed, %!STATUS!", status);
}
(void)otLwfCmdResetDevice(pFilter, TRUE);
}
otPlatResetReason
@@ -84,8 +69,8 @@ otPlatGetResetReason(
)
{
NT_ASSERT(otCtx);
UNREFERENCED_PARAMETER(otCtx); // TODO - Cache from last status for RESET
return kPlatResetReason_PowerOn;
PMS_FILTER pFilter = otCtxToFilter(otCtx);
return pFilter->cmdResetReason;
}
VOID
+1 -12
View File
@@ -571,18 +571,7 @@ otLwfThreadValueIs(
{
LogFuncEntryMsg(DRIVER_DEFAULT, "[%p] received Value for %s", pFilter, spinel_prop_key_to_cstr(key));
if (key == SPINEL_PROP_LAST_STATUS)
{
spinel_status_t status = SPINEL_STATUS_OK;
spinel_datatype_unpack(value_data_ptr, value_data_len, "i", &status);
if ((status >= SPINEL_STATUS_RESET__BEGIN) && (status <= SPINEL_STATUS_RESET__END))
{
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! was reset (status %d).", &pFilter->InterfaceGuid, status);
// TODO - Handle reset
}
}
else if (key == SPINEL_PROP_MAC_ENERGY_SCAN_RESULT)
if (key == SPINEL_PROP_MAC_ENERGY_SCAN_RESULT)
{
uint8_t scanChannel;
int8_t maxRssi;
+1 -12
View File
@@ -435,18 +435,7 @@ otLwfTunValueIs(
LogFuncEntryMsg(DRIVER_DEFAULT, "[%p] received Value for %s", pFilter, spinel_prop_key_to_cstr(key));
if (key == SPINEL_PROP_LAST_STATUS)
{
spinel_status_t status = SPINEL_STATUS_OK;
spinel_datatype_unpack(value_data_ptr, value_data_len, "i", &status);
if ((status >= SPINEL_STATUS_RESET__BEGIN) && (status <= SPINEL_STATUS_RESET__END))
{
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! was reset (status %d).", &pFilter->InterfaceGuid, status);
// TODO - Handle reset
}
}
else if (key == SPINEL_PROP_NET_ROLE)
if (key == SPINEL_PROP_NET_ROLE)
{
uint8_t value;
spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UINT8_S, &value);