From a2b58d155711fbdc4171f66fae2e5bb60f8e71e6 Mon Sep 17 00:00:00 2001 From: "yuri.benditovich@daynix.com" Date: Thu, 16 Feb 2017 16:31:00 +0200 Subject: [PATCH] qxl-wddm-dod: Simplify interrupt handling for rev4 device Do not clear interrupt mask upon interrupt. Instead clear pending interrupt status and write QXL_IO_UPDATE_IRQ register (this drops interrupt level). There are 3 advantages: 1. We do not need to wake the host to enable interrupt mask in DPC procedure (1 wake per interrupt instead of 2) 2. The driver is not sensitive to failure when queues DPC, as already queued DPC will process this interrupt when executed. 3. When we implement VSync interrupt simulation, we do not need to touch registers neither when notify the OS nor when process DPC related to this notification. Signed-off-by: Yuri Benditovich Acked-by: Frediano Ziglio --- qxldod/QxlDod.cpp | 53 ++++++++++------------------------------------- qxldod/QxlDod.h | 4 +--- 2 files changed, 12 insertions(+), 45 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 4f1f7a2..cd22446 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -4799,50 +4799,37 @@ BOOLEAN QxlDevice::InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ if (!(m_RamHdr->int_pending & m_RamHdr->int_mask)) { return FALSE; } - m_RamHdr->int_mask = 0; + m_Pending |= InterlockedExchange((LONG *)&m_RamHdr->int_pending, 0); WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_UPDATE_IRQ), 0); - m_Pending |= m_RamHdr->int_pending; - m_RamHdr->int_pending = 0; + // QXL_IO_UPDATE_IRQ sets interrupt level to m_RamHdr->int_pending & m_RamHdr->int_mask + // so it will be dropped if interrupt status is not modified after clear + if (!pDxgkInterface->DxgkCbQueueDpc(pDxgkInterface->DeviceHandle)) { - m_RamHdr->int_mask = WIN_QXL_INT_MASK; - WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_UPDATE_IRQ), 0); - DbgPrint(TRACE_LEVEL_FATAL, ("---> %s DxgkCbQueueDpc failed\n", __FUNCTION__)); + // DPC already queued and will process m_Pending when called + DbgPrint(TRACE_LEVEL_WARNING, ("---> %s can't queue Dpc for %X\n", __FUNCTION__, m_Pending)); } DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return TRUE; } QXL_NON_PAGED -VOID QxlDevice::DpcRoutine(PVOID ptr) +VOID QxlDevice::DpcRoutine(PVOID) { - PDXGKRNL_INTERFACE pDxgkInterface = (PDXGKRNL_INTERFACE)ptr; - + LONG intStatus = InterlockedExchange(&m_Pending, 0); DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__)); - DPC_CB_CONTEXT ctx; - BOOLEAN dummy; - ctx.ptr = this; - NTSTATUS Status = pDxgkInterface->DxgkCbSynchronizeExecution( - pDxgkInterface->DeviceHandle, - DpcCallbackEx, - &ctx, - 0, - &dummy); - ASSERT(Status == STATUS_SUCCESS); - if (ctx.data & QXL_INTERRUPT_DISPLAY) { + if (intStatus & QXL_INTERRUPT_DISPLAY) { DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s m_DisplayEvent\n", __FUNCTION__)); KeSetEvent (&m_DisplayEvent, IO_NO_INCREMENT, FALSE); } - if (ctx.data & QXL_INTERRUPT_CURSOR) { + if (intStatus & QXL_INTERRUPT_CURSOR) { DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s m_CursorEvent\n", __FUNCTION__)); KeSetEvent (&m_CursorEvent, IO_NO_INCREMENT, FALSE); } - if (ctx.data & QXL_INTERRUPT_IO_CMD) { + if (intStatus & QXL_INTERRUPT_IO_CMD) { DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s m_IoCmdEvent\n", __FUNCTION__)); KeSetEvent (&m_IoCmdEvent, IO_NO_INCREMENT, FALSE); } - m_RamHdr->int_mask = WIN_QXL_INT_MASK; - WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_UPDATE_IRQ), 0); DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__)); } @@ -4858,24 +4845,6 @@ VOID QxlDevice::UpdateArea(CONST RECT* area, UINT32 surface_id) DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } -QXL_NON_PAGED -BOOLEAN QxlDevice:: DpcCallbackEx(PVOID ptr) -{ - DbgPrint(TRACE_LEVEL_VERBOSE, ("<--> %s\n", __FUNCTION__)); - PDPC_CB_CONTEXT ctx = (PDPC_CB_CONTEXT) ptr; - QxlDevice* pqxl = (QxlDevice*)ctx->ptr; - pqxl->DpcCallback(ctx); - return TRUE; -} - -QXL_NON_PAGED -VOID QxlDevice::DpcCallback(PDPC_CB_CONTEXT ctx) -{ - ctx->data = m_Pending; - m_Pending = 0; - -} - QXL_NON_PAGED UINT BPPFromPixelFormat(D3DDDIFORMAT Format) { diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index 4598718..53724e8 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -549,8 +549,6 @@ private: void PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr, UINT8 **end_ptr, UINT8 *src, int size, size_t alloc_size, uint32_t alignment); - QXL_NON_PAGED BOOLEAN static DpcCallbackEx(PVOID); - QXL_NON_PAGED void DpcCallback(PDPC_CB_CONTEXT); void AsyncIo(UCHAR Port, UCHAR Value); void SyncIo(UCHAR Port, UCHAR Value); NTSTATUS UpdateChildStatus(BOOLEAN connect); @@ -602,7 +600,7 @@ private: MspaceInfo m_MSInfo[NUM_MSPACES]; UINT64 m_FreeOutputs; - UINT32 m_Pending; + LONG m_Pending; QXLMonitorsConfig* m_monitor_config; QXLPHYSICAL* m_monitor_config_pa;