summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Gurvich <pavel@daynix.com>2014-08-14 19:21:54 +0300
committerDmitry Fleytman <dfleytma@redhat.com>2014-08-17 09:30:53 +0300
commiteb1e6fc61d7395d783db9cf69484a89f25701279 (patch)
tree04cc6e8438e9b399c6f2fbd3d5a67a057846a108
parent9c891832c2cc5291a5ae06fa18e6c8b2d513189f (diff)
UsbDk: Fix never completed IOCTLs issuev0.02-1
In some cases driver sends IOCTLS to the underlying devices. It uses IoBuildDeviceIoControlRequest() function to allocate IOCTL IRP. This function allocates threaded IRP which has a number of limitations for contexts it may be sent from. In particular it must be sent from PASSIVE_LEVEL and non-arbitrary thread context to complete successfully. Since this is not always true for contexts driver sends IRPs from, never completed IOCTLs were observed on load tests. This patch fixes the problem by using IoAllocateIrp() function to allocate IOCTL IRPs. Signed-off-by: Pavel Gurvich <pavel@daynix.com> Signed-off-by: Dmitry Fleytman <dfleytma@redhat.com>
-rw-r--r--UsbDk/DeviceAccess.cpp37
-rw-r--r--UsbDk/Irp.cpp56
-rw-r--r--UsbDk/Irp.h26
3 files changed, 25 insertions, 94 deletions
diff --git a/UsbDk/DeviceAccess.cpp b/UsbDk/DeviceAccess.cpp
index 8621a0c..ed348cb 100644
--- a/UsbDk/DeviceAccess.cpp
+++ b/UsbDk/DeviceAccess.cpp
@@ -299,20 +299,27 @@ NTSTATUS CWdmDeviceAccess::QueryForInterface(const GUID &guid, __out INTERFACE &
NTSTATUS CWdmUsbDeviceAccess::Reset()
{
- CIoControlIrp Irp;
- auto status = Irp.Create(m_DevObj, IOCTL_INTERNAL_USB_CYCLE_PORT);
+ CIrp irp;
+
+ auto status = irp.Create(m_DevObj);
if (!NT_SUCCESS(status))
{
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVACCESS, "%!FUNC! Error %!STATUS! during IOCTL IRP creation", status);
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVACCESS, "%!FUNC! Error %!STATUS! during IRP creation", status);
return status;
}
- status = Irp.SendSynchronously();
+ irp.Configure([](PIO_STACK_LOCATION s)
+ {
+ s->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+ s->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_CYCLE_PORT;
+ });
+
+ status = irp.SendSynchronously();
if (!NT_SUCCESS(status))
{
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVACCESS, "%!FUNC! Send IOCTL IRP Error %!STATUS!", status);
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVACCESS, "%!FUNC! Error %!STATUS!", status);
}
return status;
@@ -438,22 +445,28 @@ bool UsbDkGetWdmDeviceIdentity(const PDEVICE_OBJECT PDO,
NTSTATUS UsbDkSendUrbSynchronously(PDEVICE_OBJECT Target, URB &Urb)
{
- CIoControlIrp Irp;
- auto status = Irp.Create(Target, IOCTL_INTERNAL_USB_SUBMIT_URB);
+ CIrp irp;
+
+ auto status = irp.Create(Target);
+
if (!NT_SUCCESS(status))
{
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVACCESS, "%!FUNC! Error %!STATUS! during IOCTL IRP creation", status);
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVACCESS, "%!FUNC! Error %!STATUS! during IRP creation", status);
return status;
}
- Irp.Configure([&Urb] (PIO_STACK_LOCATION s)
- { s->Parameters.Others.Argument1 = &Urb; });
+ irp.Configure([&Urb](PIO_STACK_LOCATION s)
+ {
+ s->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+ s->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
+ s->Parameters.Others.Argument1 = (PVOID)&Urb;
+ });
- status = Irp.SendSynchronously();
+ status = irp.SendSynchronously();
if (!NT_SUCCESS(status))
{
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVACCESS, "%!FUNC! Send URB IRP Error %!STATUS!", status);
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVACCESS, "%!FUNC! Error %!STATUS!", status);
}
return status;
diff --git a/UsbDk/Irp.cpp b/UsbDk/Irp.cpp
index eab7fa8..e4c666c 100644
--- a/UsbDk/Irp.cpp
+++ b/UsbDk/Irp.cpp
@@ -72,59 +72,3 @@ NTSTATUS CIrp::Create(PDEVICE_OBJECT TargetDevice)
m_TargetDevice = TargetDevice;
return STATUS_SUCCESS;
}
-
-CIoControlIrp::~CIoControlIrp()
-{
- if (m_TargetDevice != nullptr)
- {
- Destroy();
- }
-}
-
-void CIoControlIrp::Destroy()
-{
- ASSERT(m_TargetDevice != nullptr);
-
- ObDereferenceObject(m_TargetDevice);
- m_TargetDevice = nullptr;
-}
-
-NTSTATUS CIoControlIrp::Create(PDEVICE_OBJECT TargetDevice,
- ULONG IoControlCode,
- bool IsInternal,
- PVOID InputBuffer,
- ULONG InputBufferLength,
- PVOID OutputBuffer,
- ULONG OutputBufferLength)
-{
- m_Irp = IoBuildDeviceIoControlRequest(IoControlCode,
- TargetDevice,
- InputBuffer,
- InputBufferLength,
- OutputBuffer,
- OutputBufferLength,
- IsInternal ? TRUE : FALSE,
- m_Event,
- &m_IoControlStatus);
-
- if (m_Irp == nullptr)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- ObReferenceObject(TargetDevice);
- m_TargetDevice = TargetDevice;
- return STATUS_SUCCESS;
-}
-
-NTSTATUS CIoControlIrp::SendSynchronously()
-{
- auto res = IoCallDriver(m_TargetDevice, m_Irp);
- if (res == STATUS_PENDING)
- {
- KeWaitForSingleObject(&m_Event, Executive, KernelMode, FALSE, nullptr);
- return m_IoControlStatus.Status;
- }
-
- return res;
-}
diff --git a/UsbDk/Irp.h b/UsbDk/Irp.h
index 97e3058..7e0aa75 100644
--- a/UsbDk/Irp.h
+++ b/UsbDk/Irp.h
@@ -98,29 +98,3 @@ private:
void DestroyIrp();
void ReleaseTarget();
};
-//-------------------------------------------------------------------------------------------------
-
-class CIoControlIrp : public CIrpBase
-{
-public:
- CIoControlIrp() {}
- ~CIoControlIrp();
-
- NTSTATUS Create(PDEVICE_OBJECT TargetDevice,
- ULONG IoControlCode,
- bool IsInternal = true,
- PVOID InputBuffer = nullptr,
- ULONG InputBufferLength = 0,
- PVOID OutputBuffer = nullptr,
- ULONG OutputBufferLength = 0);
- void Destroy();
- NTSTATUS SendSynchronously();
-
- CIoControlIrp(const CIoControlIrp&) = delete;
- CIoControlIrp& operator= (const CIoControlIrp&) = delete;
-
-private:
- CWdmEvent m_Event;
- IO_STATUS_BLOCK m_IoControlStatus;
-};
-//-------------------------------------------------------------------------------------------------