[Spice-devel] [PATCH v2 4/6] qxl-wddm-dod: Simplify interrupt handling for rev4 device

Frediano Ziglio fziglio at redhat.com
Thu Feb 16 10:23:33 UTC 2017


> 
> 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 <yuri.benditovich at daynix.com>
> ---
>  qxldod/QxlDod.cpp | 54
>  ++++++++++++------------------------------------------
>  qxldod/QxlDod.h   |  4 +---
>  2 files changed, 13 insertions(+), 45 deletions(-)
> 
> diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp
> index 2d2a022..cd0a1e5 100755
> --- a/qxldod/QxlDod.cpp
> +++ b/qxldod/QxlDod.cpp
> @@ -4799,14 +4799,14 @@ 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);

I was afraid int_pending could be the wrong type or not properly
aligned but luckily it is so this line works fine (and is supposed
to continue to work).

>      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;
> @@ -4815,34 +4815,22 @@ BOOLEAN QxlDevice::InterruptRoutine(_In_
> PDXGKRNL_INTERFACE pDxgkInterface, _In_
>  QXL_NON_PAGED
>  VOID QxlDevice::DpcRoutine(PVOID ptr)
>  {
> -    PDXGKRNL_INTERFACE pDxgkInterface = (PDXGKRNL_INTERFACE)ptr;
> -
> +    LONG intStatus = InterlockedExchange(&m_Pending, 0);
> +    UNREFERENCED_PARAMETER(ptr);

I'd use 

   VOID QxlDevice::DpcRoutine(PVOID)

instead but it's just style

>      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__));
>  }
> @@ -4859,24 +4847,6 @@ VOID QxlDevice::UpdateArea(CONST RECT* area, UINT32
> surface_id)
>  }
>  
>  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)
>  {
>      switch (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;

Otherwise

Acked-by: Frediano Ziglio <fziglio at redhat.com>

Frediano


More information about the Spice-devel mailing list