mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +00:00
[NTOS:PNP] Halfplement IoInvalidateDeviceState
Implement the correct start-stop sequence for resource rebalancing without the actual rebalancing. Also move IoInvalidateDeviceState processing into the enumeration thread as it should be. CORE-17519
This commit is contained in:
parent
8f40fc7ede
commit
cf0bc1c132
4 changed files with 169 additions and 85 deletions
|
@ -527,7 +527,8 @@ typedef enum _DEVICE_ACTION
|
|||
PiActionEnumRootDevices,
|
||||
PiActionResetDevice,
|
||||
PiActionAddBootDevices,
|
||||
PiActionStartDevice
|
||||
PiActionStartDevice,
|
||||
PiActionQueryState,
|
||||
} DEVICE_ACTION;
|
||||
|
||||
//
|
||||
|
@ -1403,6 +1404,16 @@ PiIrpQueryDeviceRelations(
|
|||
_In_ PDEVICE_NODE DeviceNode,
|
||||
_In_ DEVICE_RELATION_TYPE Type);
|
||||
|
||||
NTSTATUS
|
||||
PiIrpQueryResources(
|
||||
_In_ PDEVICE_NODE DeviceNode,
|
||||
_Out_ PCM_RESOURCE_LIST *Resources);
|
||||
|
||||
NTSTATUS
|
||||
PiIrpQueryResourceRequirements(
|
||||
_In_ PDEVICE_NODE DeviceNode,
|
||||
_Out_ PIO_RESOURCE_REQUIREMENTS_LIST *Resources);
|
||||
|
||||
NTSTATUS
|
||||
PiIrpQueryDeviceText(
|
||||
_In_ PDEVICE_NODE DeviceNode,
|
||||
|
|
|
@ -1552,8 +1552,8 @@ PiStartDeviceFinal(
|
|||
DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status);
|
||||
}
|
||||
|
||||
/* Invalidate device state so IRP_MN_QUERY_PNP_DEVICE_STATE is sent */
|
||||
IoInvalidateDeviceState(DeviceNode->PhysicalDeviceObject);
|
||||
// Query the device state (IRP_MN_QUERY_PNP_DEVICE_STATE)
|
||||
PiQueueDeviceAction(DeviceNode->PhysicalDeviceObject, PiActionQueryState, NULL, NULL);
|
||||
|
||||
DPRINT("Sending GUID_DEVICE_ARRIVAL %wZ\n", &DeviceNode->InstancePath);
|
||||
IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, &DeviceNode->InstancePath);
|
||||
|
@ -2025,25 +2025,27 @@ IopRemoveDevice(PDEVICE_NODE DeviceNode)
|
|||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
/**
|
||||
* @brief Processes the IoInvalidateDeviceState request
|
||||
*
|
||||
* Sends IRP_MN_QUERY_PNP_DEVICE_STATE request and sets device node's flags
|
||||
* according to the result.
|
||||
* Tree reenumeration should be started upon a successful return of the function.
|
||||
*
|
||||
* @todo Do not return STATUS_SUCCESS if nothing is changed.
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject)
|
||||
static
|
||||
NTSTATUS
|
||||
PiUpdateDeviceState(
|
||||
_In_ PDEVICE_NODE DeviceNode)
|
||||
{
|
||||
PDEVICE_NODE DeviceNode = IopGetDeviceNode(PhysicalDeviceObject);
|
||||
PNP_DEVICE_STATE PnPFlags;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = PiIrpQueryPnPDeviceState(DeviceNode, &PnPFlags);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
if (Status != STATUS_NOT_SUPPORTED)
|
||||
{
|
||||
DPRINT1("IRP_MN_QUERY_PNP_DEVICE_STATE failed with status 0x%lx\n", Status);
|
||||
}
|
||||
return;
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (PnPFlags & PNP_DEVICE_NOT_DISABLEABLE)
|
||||
|
@ -2056,83 +2058,37 @@ IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject)
|
|||
else
|
||||
DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
|
||||
|
||||
if ((PnPFlags & PNP_DEVICE_REMOVED) ||
|
||||
((PnPFlags & PNP_DEVICE_FAILED) && !(PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)))
|
||||
if (PnPFlags & PNP_DEVICE_REMOVED || PnPFlags & PNP_DEVICE_DISABLED)
|
||||
{
|
||||
/* Flag it if it's failed */
|
||||
if (PnPFlags & PNP_DEVICE_FAILED)
|
||||
{
|
||||
PiSetDevNodeProblem(DeviceNode, CM_PROB_FAILED_POST_START);
|
||||
}
|
||||
PiSetDevNodeProblem(DeviceNode,
|
||||
PnPFlags & PNP_DEVICE_DISABLED
|
||||
? CM_PROB_HARDWARE_DISABLED
|
||||
: CM_PROB_DEVICE_NOT_THERE);
|
||||
|
||||
DeviceNode->Flags |= DNF_DEVICE_GONE;
|
||||
PiSetDevNodeState(DeviceNode, DeviceNodeAwaitingQueuedRemoval);
|
||||
}
|
||||
// it doesn't work anyway. A real resource rebalancing should be implemented
|
||||
#if 0
|
||||
else if ((PnPFlags & PNP_DEVICE_FAILED) && (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED))
|
||||
else if (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)
|
||||
{
|
||||
/* Stop for resource rebalance */
|
||||
Status = IopStopDevice(DeviceNode);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to stop device for rebalancing\n");
|
||||
// Query resource rebalance
|
||||
|
||||
/* Stop failed so don't rebalance */
|
||||
PnPFlags &= ~PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED;
|
||||
}
|
||||
if (PnPFlags & PNP_DEVICE_FAILED)
|
||||
DeviceNode->Flags &= DNF_NON_STOPPED_REBALANCE;
|
||||
else
|
||||
DeviceNode->Flags |= DNF_NON_STOPPED_REBALANCE;
|
||||
|
||||
// Clear DNF_NO_RESOURCE_REQUIRED just in case (will be set back if needed)
|
||||
DeviceNode->Flags &= ~DNF_NO_RESOURCE_REQUIRED;
|
||||
|
||||
// This will be caught up later by enumeration
|
||||
DeviceNode->Flags |= DNF_RESOURCE_REQUIREMENTS_CHANGED;
|
||||
}
|
||||
else if (PnPFlags & PNP_DEVICE_FAILED)
|
||||
{
|
||||
PiSetDevNodeProblem(DeviceNode, CM_PROB_FAILED_POST_START);
|
||||
PiSetDevNodeState(DeviceNode, DeviceNodeAwaitingQueuedRemoval);
|
||||
}
|
||||
|
||||
/* Resource rebalance */
|
||||
if (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)
|
||||
{
|
||||
DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
|
||||
|
||||
Status = IopInitiatePnpIrp(PhysicalDeviceObject,
|
||||
&IoStatusBlock,
|
||||
IRP_MN_QUERY_RESOURCES,
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status) && IoStatusBlock.Information)
|
||||
{
|
||||
DeviceNode->BootResources =
|
||||
(PCM_RESOURCE_LIST)IoStatusBlock.Information;
|
||||
IopDeviceNodeSetFlag(DeviceNode, DNF_HAS_BOOT_CONFIG);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
|
||||
DeviceNode->BootResources = NULL;
|
||||
}
|
||||
|
||||
DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
|
||||
|
||||
Status = IopInitiatePnpIrp(PhysicalDeviceObject,
|
||||
&IoStatusBlock,
|
||||
IRP_MN_QUERY_RESOURCE_REQUIREMENTS,
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
DeviceNode->ResourceRequirements =
|
||||
(PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status);
|
||||
DeviceNode->ResourceRequirements = NULL;
|
||||
}
|
||||
|
||||
/* IRP_MN_FILTER_RESOURCE_REQUIREMENTS is called indirectly by IopStartDevice */
|
||||
if (IopStartDevice(DeviceNode) != STATUS_SUCCESS)
|
||||
{
|
||||
DPRINT1("Restart after resource rebalance failed\n");
|
||||
|
||||
DeviceNode->Flags &= ~(DNF_STARTED | DNF_START_REQUEST_PENDING);
|
||||
DeviceNode->Flags |= DNF_START_FAILED;
|
||||
|
||||
IopRemoveDevice(DeviceNode);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static
|
||||
|
@ -2327,6 +2283,30 @@ cleanup:
|
|||
&DeviceNode->InstancePath);
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
PiFakeResourceRebalance(
|
||||
_In_ PDEVICE_NODE DeviceNode)
|
||||
{
|
||||
ASSERT(DeviceNode->Flags & DNF_RESOURCE_REQUIREMENTS_CHANGED);
|
||||
|
||||
PCM_RESOURCE_LIST bootConfig = NULL;
|
||||
PIO_RESOURCE_REQUIREMENTS_LIST resourceRequirements = NULL;
|
||||
|
||||
PiIrpQueryResources(DeviceNode, &bootConfig);
|
||||
PiIrpQueryResourceRequirements(DeviceNode, &resourceRequirements);
|
||||
|
||||
DeviceNode->BootResources = bootConfig;
|
||||
DeviceNode->ResourceRequirements = resourceRequirements;
|
||||
|
||||
if (bootConfig)
|
||||
{
|
||||
DeviceNode->Flags |= DNF_HAS_BOOT_CONFIG;
|
||||
}
|
||||
|
||||
DeviceNode->Flags &= ~DNF_RESOURCE_REQUIREMENTS_CHANGED;
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
PiDevNodeStateMachine(
|
||||
|
@ -2420,12 +2400,28 @@ PiDevNodeStateMachine(
|
|||
PiSetDevNodeState(currentNode, DeviceNodeEnumerateCompletion);
|
||||
doProcessAgain = TRUE;
|
||||
}
|
||||
else if (currentNode->Flags & DNF_RESOURCE_REQUIREMENTS_CHANGED)
|
||||
{
|
||||
if (currentNode->Flags & DNF_NON_STOPPED_REBALANCE)
|
||||
{
|
||||
PiFakeResourceRebalance(currentNode);
|
||||
currentNode->Flags &= ~DNF_NON_STOPPED_REBALANCE;
|
||||
}
|
||||
else
|
||||
{
|
||||
PiIrpQueryStopDevice(currentNode);
|
||||
PiSetDevNodeState(currentNode, DeviceNodeQueryStopped);
|
||||
}
|
||||
|
||||
doProcessAgain = TRUE;
|
||||
}
|
||||
break;
|
||||
case DeviceNodeQueryStopped:
|
||||
// we're here after sending IRP_MN_QUERY_STOP_DEVICE
|
||||
status = currentNode->CompletionStatus;
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
PiIrpStopDevice(currentNode);
|
||||
PiSetDevNodeState(currentNode, DeviceNodeStopped);
|
||||
}
|
||||
else
|
||||
|
@ -2433,10 +2429,14 @@ PiDevNodeStateMachine(
|
|||
PiIrpCancelStopDevice(currentNode);
|
||||
PiSetDevNodeState(currentNode, DeviceNodeStarted);
|
||||
}
|
||||
doProcessAgain = TRUE;
|
||||
break;
|
||||
case DeviceNodeStopped:
|
||||
// TODO: do resource rebalance (not implemented)
|
||||
ASSERT(FALSE);
|
||||
PiFakeResourceRebalance(currentNode);
|
||||
|
||||
PiSetDevNodeState(currentNode, DeviceNodeDriversAdded);
|
||||
doProcessAgain = TRUE;
|
||||
break;
|
||||
case DeviceNodeRestartCompletion:
|
||||
break;
|
||||
|
@ -2522,6 +2522,8 @@ ActionToStr(
|
|||
return "PiActionAddBootDevices";
|
||||
case PiActionStartDevice:
|
||||
return "PiActionStartDevice";
|
||||
case PiActionQueryState:
|
||||
return "PiActionQueryState";
|
||||
default:
|
||||
return "(request unknown)";
|
||||
}
|
||||
|
@ -2596,6 +2598,16 @@ PipDeviceActionWorker(
|
|||
}
|
||||
break;
|
||||
|
||||
case PiActionQueryState:
|
||||
// First, do a IRP_MN_QUERY_PNP_DEVICE_STATE request,
|
||||
// it will update node's flags and then do enumeration if something changed
|
||||
status = PiUpdateDeviceState(deviceNode);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
PiDevNodeStateMachine(deviceNode);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINT1("Unimplemented device action %u\n", Request->Action);
|
||||
status = STATUS_NOT_IMPLEMENTED;
|
||||
|
|
|
@ -196,6 +196,58 @@ PiIrpQueryDeviceRelations(
|
|||
return status;
|
||||
}
|
||||
|
||||
// IRP_MN_QUERY_RESOURCES (0x0A)
|
||||
NTSTATUS
|
||||
PiIrpQueryResources(
|
||||
_In_ PDEVICE_NODE DeviceNode,
|
||||
_Out_ PCM_RESOURCE_LIST *Resources)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(DeviceNode);
|
||||
|
||||
ULONG_PTR longRes;
|
||||
IO_STACK_LOCATION stack = {
|
||||
.MajorFunction = IRP_MJ_PNP,
|
||||
.MinorFunction = IRP_MN_QUERY_RESOURCES
|
||||
};
|
||||
|
||||
NTSTATUS status;
|
||||
status = IopSynchronousCall(DeviceNode->PhysicalDeviceObject, &stack, (PVOID)&longRes);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
*Resources = (PVOID)longRes;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// IRP_MN_QUERY_RESOURCE_REQUIREMENTS (0x0B)
|
||||
NTSTATUS
|
||||
PiIrpQueryResourceRequirements(
|
||||
_In_ PDEVICE_NODE DeviceNode,
|
||||
_Out_ PIO_RESOURCE_REQUIREMENTS_LIST *Resources)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(DeviceNode);
|
||||
|
||||
ULONG_PTR longRes;
|
||||
IO_STACK_LOCATION stack = {
|
||||
.MajorFunction = IRP_MJ_PNP,
|
||||
.MinorFunction = IRP_MN_QUERY_RESOURCE_REQUIREMENTS
|
||||
};
|
||||
|
||||
NTSTATUS status;
|
||||
status = IopSynchronousCall(DeviceNode->PhysicalDeviceObject, &stack, (PVOID)&longRes);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
*Resources = (PVOID)longRes;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// IRP_MN_QUERY_DEVICE_TEXT (0x0C)
|
||||
NTSTATUS
|
||||
PiIrpQueryDeviceText(
|
||||
|
@ -236,7 +288,8 @@ PiIrpQueryPnPDeviceState(
|
|||
PAGED_CODE();
|
||||
|
||||
ASSERT(DeviceNode);
|
||||
ASSERT(DeviceNode->State == DeviceNodeStartPostWork ||
|
||||
ASSERT(DeviceNode->State == DeviceNodeResourcesAssigned ||
|
||||
DeviceNode->State == DeviceNodeStartPostWork ||
|
||||
DeviceNode->State == DeviceNodeStarted);
|
||||
|
||||
ULONG_PTR longState;
|
||||
|
|
|
@ -2412,3 +2412,11 @@ IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
|
|||
AddressSpace,
|
||||
TranslatedAddress);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
IoInvalidateDeviceState(
|
||||
IN PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PiQueueDeviceAction(DeviceObject, PiActionQueryState, NULL, NULL);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue