VIGS: Fix fence ack losses 41/16641/1
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Thu, 20 Feb 2014 07:57:39 +0000 (11:57 +0400)
committerStanislav Vorobiov <s.vorobiov@samsung.com>
Thu, 20 Feb 2014 07:57:39 +0000 (11:57 +0400)
It's incorrect to have vblank enable/disable flag
in INT register, it can cause fence ack losses, consider
the following scenario:
1. Fence interrupt is set on host, fence_pending bit is
   set in INT register
2. vblank is turned off on guest, INT register is being
   written to and since fence_pending bit is 1 it's
   CLEARED on host
3. Now guest handles fence IRQ, but fence_pending bit
   is 0, thus, fence ack is lost

The solution is to have separate register - CON and
vblank enable/disable bit should be there

Change-Id: I1ff97d4cf8cddaec65dfe9d4c1afef3d901b4825

hw/vigs/vigs_device.c
hw/vigs/vigs_regs.h

index 0f3944d8aca1cb90086448a0453a9206821ccf9b..7b16d3af520d41141236ad2a457de4d8812127d3 100644 (file)
@@ -71,6 +71,7 @@ typedef struct VIGSState
      */
     QemuConsole *con;
 
+    uint32_t reg_con;
     uint32_t reg_int;
 } VIGSState;
 
@@ -82,7 +83,7 @@ static void vigs_update_irq(VIGSState *s)
 {
     bool raise = false;
 
-    if ((s->reg_int & VIGS_REG_INT_VBLANK_ENABLE) &&
+    if ((s->reg_con & VIGS_REG_CON_VBLANK_ENABLE) &&
         (s->reg_int & VIGS_REG_INT_VBLANK_PENDING)) {
         raise = true;
     }
@@ -122,7 +123,7 @@ static void vigs_hw_update(void *opaque)
 
     dpy_gfx_update(s->con, 0, 0, surface_width(ds), surface_height(ds));
 
-    if (s->reg_int & VIGS_REG_INT_VBLANK_ENABLE) {
+    if (s->reg_con & VIGS_REG_CON_VBLANK_ENABLE) {
         s->reg_int |= VIGS_REG_INT_VBLANK_PENDING;
         vigs_update_irq(s);
     }
@@ -140,8 +141,7 @@ static void vigs_dpy_resize(void *user_data,
     DisplaySurface *ds = qemu_console_surface(s->con);
 
     if ((width != surface_width(ds)) ||
-        (height != surface_height(ds)))
-    {
+        (height != surface_height(ds))) {
         qemu_console_resize(s->con, width, height);
     }
 }
@@ -186,6 +186,8 @@ static uint64_t vigs_io_read(void *opaque, hwaddr offset,
     VIGSState *s = opaque;
 
     switch (offset) {
+    case VIGS_REG_CON:
+        return s->reg_con;
     case VIGS_REG_INT:
         return s->reg_int;
     case VIGS_REG_FENCE_LOWER:
@@ -209,6 +211,19 @@ static void vigs_io_write(void *opaque, hwaddr offset,
     case VIGS_REG_EXEC:
         vigs_server_dispatch(s->server, value);
         break;
+    case VIGS_REG_CON:
+        if (((s->reg_con & VIGS_REG_CON_VBLANK_ENABLE) == 0) &&
+            (value & VIGS_REG_CON_VBLANK_ENABLE)) {
+            VIGS_LOG_DEBUG("VBLANK On");
+        } else if (((value & VIGS_REG_CON_VBLANK_ENABLE) == 0) &&
+                   (s->reg_con & VIGS_REG_CON_VBLANK_ENABLE)) {
+            VIGS_LOG_DEBUG("VBLANK Off");
+        }
+
+        s->reg_con = value & VIGS_REG_CON_MASK;
+
+        vigs_update_irq(s);
+        break;
     case VIGS_REG_INT:
         if (value & VIGS_REG_INT_VBLANK_PENDING) {
             value &= ~VIGS_REG_INT_VBLANK_PENDING;
@@ -222,14 +237,6 @@ static void vigs_io_write(void *opaque, hwaddr offset,
             value |= (s->reg_int & VIGS_REG_INT_FENCE_ACK_PENDING);
         }
 
-        if (((s->reg_int & VIGS_REG_INT_VBLANK_ENABLE) == 0) &&
-            (value & VIGS_REG_INT_VBLANK_ENABLE)) {
-            VIGS_LOG_DEBUG("VBLANK On");
-        } else if (((value & VIGS_REG_INT_VBLANK_ENABLE) == 0) &&
-                   (s->reg_int & VIGS_REG_INT_VBLANK_ENABLE)) {
-            VIGS_LOG_DEBUG("VBLANK Off");
-        }
-
         s->reg_int = value & VIGS_REG_INT_MASK;
 
         vigs_update_irq(s);
@@ -371,6 +378,7 @@ static void vigs_device_reset(DeviceState *d)
 
     pci_set_irq(&s->dev.pci_dev, 0);
 
+    s->reg_con = 0;
     s->reg_int = 0;
 
     VIGS_LOG_INFO("VIGS reset");
index dd069b3c4c1d5f819b33a918a22f2b22398e52b9..efcb7064563676a27f5641b9a282829b41dd7299 100644 (file)
 #define _QEMU_VIGS_REGS_H
 
 #define VIGS_REG_EXEC 0
-#define VIGS_REG_INT 8
-#define VIGS_REG_FENCE_LOWER 16
-#define VIGS_REG_FENCE_UPPER 24
+#define VIGS_REG_CON 8
+#define VIGS_REG_INT 16
+#define VIGS_REG_FENCE_LOWER 24
+#define VIGS_REG_FENCE_UPPER 32
 
-#define VIGS_REG_INT_MASK 7
-#define VIGS_REG_INT_VBLANK_ENABLE 1
-#define VIGS_REG_INT_VBLANK_PENDING 2
-#define VIGS_REG_INT_FENCE_ACK_PENDING 4
+#define VIGS_REG_CON_MASK 1
+#define VIGS_REG_CON_VBLANK_ENABLE 1
+
+#define VIGS_REG_INT_MASK 3
+#define VIGS_REG_INT_VBLANK_PENDING 1
+#define VIGS_REG_INT_FENCE_ACK_PENDING 2
 
 #endif