Skip to content

Commit 1332ad1

Browse files
author
Martin Drab
committed
[vioser]: Handle surprise removal for serial ports
When the Virtio serial port gets surprise removed, let's complete the pending read request sent by QGA with STATUS_DELETE_PENDING. If QGA is run as a service, it reports an error, closes handles to all Virtio serial devices and starts waiting for their reappearance. Closing the handles permits the PnP Manager to remove the serial devices. If the handles stayed open, the system would hang indefinitely. Signed-Off-By: Martin Drab <[email protected]>
1 parent 848e84f commit 1332ad1

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

vioserial/sys/Port.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ EVT_WDF_REQUEST_CANCEL VIOSerialPortReadRequestCancel;
1414
EVT_WDF_DEVICE_D0_ENTRY VIOSerialPortEvtDeviceD0Entry;
1515
EVT_WDF_DEVICE_D0_EXIT VIOSerialPortEvtDeviceD0Exit;
1616
EVT_WDF_DEVICE_QUERY_REMOVE VIOSerialPortEvtDeviceQueryRemove;
17+
EVT_WDF_DEVICE_SURPRISE_REMOVAL VIOSerialPortEvtDeviceSurpriseRemoval;
1718

1819
#ifdef ALLOC_PRAGMA
1920
#pragma alloc_text(PAGE, VIOSerialDeviceListCreatePdo)
2021
#pragma alloc_text(PAGE, VIOSerialPortWrite)
2122
#pragma alloc_text(PAGE, VIOSerialPortDeviceControl)
2223
#pragma alloc_text(PAGE, VIOSerialPortEvtDeviceD0Entry)
2324
#pragma alloc_text(PAGE, VIOSerialPortEvtDeviceQueryRemove)
25+
#pragma alloc_text(PAGE, VIOSerialPortEvtDeviceSurpriseRemoval)
2426
#endif
2527

2628
PVIOSERIAL_PORT
@@ -364,6 +366,7 @@ VIOSerialDeviceListCreatePdo(IN WDFCHILDLIST DeviceList,
364366
PnpPowerCallbacks.EvtDeviceD0Entry = VIOSerialPortEvtDeviceD0Entry;
365367
PnpPowerCallbacks.EvtDeviceD0Exit = VIOSerialPortEvtDeviceD0Exit;
366368
PnpPowerCallbacks.EvtDeviceQueryRemove = VIOSerialPortEvtDeviceQueryRemove;
369+
PnpPowerCallbacks.EvtDeviceSurpriseRemoval = VIOSerialPortEvtDeviceSurpriseRemoval;
367370
WdfDeviceInitSetPnpPowerEventCallbacks(ChildInit, &PnpPowerCallbacks);
368371

369372
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, RAWPDO_VIOSERIAL_PORT);
@@ -1292,6 +1295,33 @@ NTSTATUS VIOSerialPortEvtDeviceQueryRemove(WDFDEVICE Device)
12921295
return STATUS_SUCCESS;
12931296
}
12941297

1298+
VOID VIOSerialPortEvtDeviceSurpriseRemoval(WDFDEVICE Device)
1299+
{
1300+
WDFREQUEST readRequest = NULL;
1301+
PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData(Device);
1302+
PVIOSERIAL_PORT port = pdoData->port;
1303+
1304+
TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__);
1305+
1306+
WdfSpinLockAcquire(port->InBufLock);
1307+
readRequest = port->PendingReadRequest;
1308+
port->PendingReadRequest = NULL;
1309+
if (readRequest != NULL)
1310+
{
1311+
if (WdfRequestUnmarkCancelable(readRequest) != STATUS_CANCELLED)
1312+
{
1313+
WdfRequestCompleteWithInformation(readRequest, STATUS_DELETE_PENDING, 0L);
1314+
}
1315+
}
1316+
1317+
port->Removed = TRUE;
1318+
WdfSpinLockRelease(port->InBufLock);
1319+
1320+
TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s\n", __FUNCTION__);
1321+
1322+
return;
1323+
}
1324+
12951325
NTSTATUS VIOSerialPortEvtDeviceD0Entry(IN WDFDEVICE Device, IN WDF_POWER_DEVICE_STATE PreviousState)
12961326
{
12971327
PVIOSERIAL_PORT port = RawPdoSerialPortGetData(Device)->port;

0 commit comments

Comments
 (0)