summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYonit Halperin <yhalperi@redhat.com>2010-07-12 16:37:03 +0300
committerYonit Halperin <yhalperi@redhat.com>2010-07-14 08:33:25 +0300
commit3f1b5fffa0474e1c31950bfd5dbbed02c78dc380 (patch)
treec3d09166e541692ae5e80bbaac32bd6560b0f1c7
parentf55b4857ed8a828f75c2034e6d1bbec60d56abc1 (diff)
Fix corrupted ram data (e.g., release_ring), and unsynchronized worker, after driver is disabled and re-enabled.
On logoff, in Win7 guest, and on switch user and login into a Winxp guest, the driver is disabled and re-enabled (while the miniport in not reset). However, before the fix, all the draw objects, e.g., surfaces, were still alive in the worker and the release ring still contained objects, while all the driver's data was initialized. This caused blue screens, and panics in the worker.
-rw-r--r--display/driver.c1
-rw-r--r--display/qxldd.h1
-rw-r--r--display/res.c21
-rw-r--r--display/res.h2
4 files changed, 25 insertions, 0 deletions
diff --git a/display/driver.c b/display/driver.c
index 7dce00e..4eaedc4 100644
--- a/display/driver.c
+++ b/display/driver.c
@@ -256,6 +256,7 @@ BOOL DrvEnableDriver(ULONG engine_version, ULONG enable_data_size, PDRVENABLEDAT
VOID DrvDisableDriver(VOID)
{
DEBUG_PRINT((NULL, 1, "%s\n", __FUNCTION__));
+ ResetAllDevices();
ResDestroyGlobals();
CleanGlobalRes();
}
diff --git a/display/qxldd.h b/display/qxldd.h
index ffa8b8c..b90aaad 100644
--- a/display/qxldd.h
+++ b/display/qxldd.h
@@ -168,6 +168,7 @@ typedef struct DevRes {
UINT8 *surfaces_used;
+ HANDLE driver;
#ifdef DBG
int num_free_pages;
int num_outputs;
diff --git a/display/res.c b/display/res.c
index c769aeb..a8357f7 100644
--- a/display/res.c
+++ b/display/res.c
@@ -28,6 +28,8 @@
#include "surface.h"
#include "dd.h"
#include "rop.h"
+#include "devioctl.h"
+#include "ntddvdeo.h"
#if (WINVER < 0x0501)
#define WAIT_FOR_EVENT(pdev, event, timeout) (pdev)->WaitForEvent(event, timeout)
@@ -397,6 +399,8 @@ static void InitRes(PDev *pdev)
RtlZeroMemory(pdev->Res.palette_cache, sizeof(pdev->Res.palette_cache));
RingInit(&pdev->Res.dynamic->palette_lru);
pdev->Res.num_palettes = 0;
+
+ pdev->Res.driver = pdev->driver;
ONDBG(pdev->Res.num_outputs = 0);
ONDBG(pdev->Res.num_path_pages = 0);
@@ -3156,5 +3160,22 @@ void CheckAndSetSSE2()
}
}
+void ResetAllDevices()
+{
+ UINT32 i;
+ EngAcquireSemaphore(res_sem);
+ for (i = 0; i < num_global_res; i++) {
+ if (global_res[i].driver) {
+ DWORD length;
+ if (EngDeviceIoControl(global_res[i].driver, IOCTL_VIDEO_RESET_DEVICE,
+ NULL, 0, NULL, 0, &length)) {
+ DEBUG_PRINT((NULL, 0, "%s: reset to device failed 0x%lx\n",
+ __FUNCTION__, global_res[i].driver));
+
+ }
+ }
+ }
+ EngReleaseSemaphore(res_sem);
+}
diff --git a/display/res.h b/display/res.h
index 3bfb0c7..7a10035 100644
--- a/display/res.h
+++ b/display/res.h
@@ -63,4 +63,6 @@ void ResDestroy(PDev *pdev);
void ResInitGlobals();
void ResDestroyGlobals();
void CheckAndSetSSE2();
+void ResetAllDevices();
+
#endif