[Spice-devel] [RFC qxl-win 2/2] display: handle interrupt handler disappearance (rhbz 721118)
Uri Lublin
uril at redhat.com
Wed Sep 21 10:09:44 PDT 2011
On 09/21/2011 04:13 PM, Alon Levy wrote:
> This patch handles the surprise removal whql test. The surprise
> removal test sends a surprise removal IRP via a filter driver to
> qxl.sys. The handling of that IRP is actually done in videoprt.sys,
> and there is no API to get notified. The side effect of the handler
> in videoprt.sys is disabling our interrupt handler. This patch takes
> care of continuing to work after our interrupt is disabled. This is
> in effect the opposite of what the MSDN states that a device should do
> after a surprise removal, since the MSDN requires every IO to fail after
> the surprise removal IRP has been successfully handled. On the other
> hand, this workaround is sufficient to pass the test.
>
> The workaround is to turn the EngWaitForSingleEvent on the io_cmd_event
> event into a timed wait.
>
> If it fails, we revert to synchronouse IO, which doesn't require that
> event at all.
> ---
> display/qxldd.h | 39 ++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 38 insertions(+), 1 deletions(-)
>
> diff --git a/display/qxldd.h b/display/qxldd.h
> @@ -449,10 +468,28 @@ static _inline RingItem *RingGetTail(PDev *pdev, Ring *ring)
> */
> static _inline void async_io(PDev *pdev, asyncable_t op, UCHAR val)
> {
> + ENG_TIME_FIELDS start, finish;
> + LARGE_INTEGER timeout; // 1 => 100 nanoseconds
> + ULONG64 millis;
> +
> if (pdev->use_async) {
> EngAcquireSemaphore(pdev->io_sem);
> WRITE_PORT_UCHAR(pdev->asyncable[op][ASYNC], val);
> - WAIT_FOR_EVENT(pdev, pdev->io_cmd_event, NULL);
> + /* Our Interrupt may be taken from us unexpectedly, by a surprise removal.
> + * in which case this event will never be set. This happens only during WHQL
> + * tests (pnpdtest /surprise). So instead: Wait on a timer, if we fail, stop waiting, until
> + * we get reset. We use EngQueryLocalTime because there is no way to differentiate a return on
> + * timeout from a return on event set otherwise. */
A couple of suggestions:
1. Can you use time() ? It would make the code a little bit simpler.
2. Is the timeout long enough (2 seconds) ? Maybe use a longer timeout for
surprise removal.
> + timeout.QuadPart = -INTERRUPT_NOT_PRESENT_TIMEOUT_100NS; // negative => relative
> + DEBUG_PRINT((pdev, 15, "WAIT_FOR_EVENT %d\n", (int)op));
> + EngQueryLocalTime(&start);
> + WAIT_FOR_EVENT(pdev, pdev->io_cmd_event,&timeout);
> + EngQueryLocalTime(&finish);
> + millis = eng_time_diff_ms(&finish,&start);
> + if (millis>= INTERRUPT_NOT_PRESENT_TIMEOUT_MS) {
> + pdev->use_async = 0;
> + DEBUG_PRINT((pdev, 0, "%s: timeout reached, disabling async io!\n", __FUNCTION__));
> + }
> EngReleaseSemaphore(pdev->io_sem);
> DEBUG_PRINT((pdev, 3, "finished async %d\n", (int)op));
> } else {
More information about the Spice-devel
mailing list