diff mbox

[2/3] pseries: Fix bug with reset of VIO CRQs

Message ID 1332970787-14598-2-git-send-email-david@gibson.dropbear.id.au
State New
Headers show

Commit Message

David Gibson March 28, 2012, 9:39 p.m. UTC
PAPR specifies a Command Response Queue (CRQ) mechanism used for virtual
IO, which we implement.  However, we don't correctly clean up registered
CRQs when we reset the system.

This patch adds a reset handler to fix this bug.  While we're at it, add
in some of the extra debug messages that were used to track the problem
down.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/spapr_vio.c |   33 +++++++++++++++++++++++++--------
 1 files changed, 25 insertions(+), 8 deletions(-)

Comments

Andreas Färber April 10, 2012, 2:51 p.m. UTC | #1
Am 28.03.2012 23:39, schrieb David Gibson:
> PAPR specifies a Command Response Queue (CRQ) mechanism used for virtual
> IO, which we implement.  However, we don't correctly clean up registered
> CRQs when we reset the system.
> 
> This patch adds a reset handler to fix this bug.  While we're at it, add
> in some of the extra debug messages that were used to track the problem
> down.
> 
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---

Thanks, applied the modified version to ppc-next:
http://repo.or.cz/w/qemu/agraf.git/shortlog/refs/heads/ppc-next

Andreas
diff mbox

Patch

diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 1f67e64..97d029a 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -431,12 +431,13 @@  static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr,
 
     /* Check if device supports CRQs */
     if (!dev->crq.SendFunc) {
+        hcall_dprintf("h_reg_crq, device does not support CRQ\n");
         return H_NOT_FOUND;
     }
 
-
     /* Already a queue ? */
     if (dev->crq.qsize) {
+        hcall_dprintf("h_reg_crq, CRQ already registered\n");
         return H_RESOURCE;
     }
     dev->crq.qladdr = queue_addr;
@@ -449,6 +450,17 @@  static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr,
     return H_SUCCESS;
 }
 
+static target_ulong free_crq(VIOsPAPRDevice *dev)
+{
+    dev->crq.qladdr = 0;
+    dev->crq.qsize = 0;
+    dev->crq.qnext = 0;
+
+    dprintf("CRQ for dev 0x%" PRIx32 " freed\n", dev->reg);
+
+    return H_SUCCESS;
+}
+
 static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr,
                                target_ulong opcode, target_ulong *args)
 {
@@ -460,13 +472,7 @@  static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr,
         return H_PARAMETER;
     }
 
-    dev->crq.qladdr = 0;
-    dev->crq.qsize = 0;
-    dev->crq.qnext = 0;
-
-    dprintf("CRQ for dev 0x" TARGET_FMT_lx " freed\n", reg);
-
-    return H_SUCCESS;
+    return free_crq(dev);
 }
 
 static target_ulong h_send_crq(CPUPPCState *env, sPAPREnvironment *spapr,
@@ -642,6 +648,15 @@  static int spapr_vio_check_reg(VIOsPAPRDevice *sdev)
     return 0;
 }
 
+static void spapr_vio_busdev_reset(void *opaque)
+{
+    VIOsPAPRDevice *dev = (VIOsPAPRDevice *)opaque;
+
+    if (dev->crq.qsize) {
+        free_crq(dev);
+    }
+}
+
 static int spapr_vio_busdev_init(DeviceState *qdev)
 {
     VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
@@ -670,6 +685,8 @@  static int spapr_vio_busdev_init(DeviceState *qdev)
 
     rtce_init(dev);
 
+    qemu_register_reset(spapr_vio_busdev_reset, dev);
+
     return pc->init(dev);
 }